the media9 package - concertpass.com mirror...

37
The media9 Package, v0.96 Alexander Grahn 21st February 2019 Abstract AL A T E X package for embedding interactive Adobe Flash (SWF) and 3D les (Adobe U3D & PRC) as well as video and sound les or streams (FLV, MP4/H.246, MP3) into PDF documents with Adobe Reader-9/X compatibility. Keywords: embed ash movie LaTeX pdf 3d include sound swf mp3 video mp4 h.264 aac slideshow image gallery v audio multimedia streamed media rtmp YouTube animation JavaScript pdfLaTeX dvips ps2pdf dvipdfmx XeLaTeX u3d prc Adobe Reader Foxit RichMedia annotation LuaLaTeX Contents 1 Introduction 2 Requirements 3 Installation 4 Using the package 5 The user interface 5.1 Media inclusion .............................. 5.2 Command options ............................. 5.3 Control buttons .............................. 6 Embedding Flash, video and sound, image slide-shows (with examples) 7 Embedding 3D objects (with examples) 7.1 Introduction ................................ 7.2 3D quick-start guide ............................ 8 Caveats 9 Acknowledgements 1

Upload: truongminh

Post on 21-Mar-2019

220 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

The media9 Package v096

Alexander Grahnhttpsgitlabcomagrahnmedia9httpsgitlabcomagrahnmedia9

21st February 2019

Abstract

A LATEX package for embedding interactive Adobe Flash (SWF) and 3D les (AdobeU3D amp PRC) as well as video and sound les or streams (FLV MP4H246 MP3)into PDF documents with Adobe Reader-9X compatibility

Keywords embed ash movie LaTeX pdf 3d include sound swf mp3 video mp4h264 aac slideshow image gallery v audio multimedia streamed media rtmpYouTube animation JavaScript pdfLaTeX dvips ps2pdf dvipdfmx XeLaTeX u3d prcAdobe Reader Foxit RichMedia annotation LuaLaTeX

Contents1 Introduction 2

2 Requirements 3

3 Installation 3

4 Using the package 4

5 The user interface 5

51 Media inclusion 5

52 Command options 6

53 Control buttons 16

6 Embedding Flash video and sound image slide-shows (with examples) 18

7 Embedding 3D objects (with examples) 30

71 Introduction 30

72 3D quick-start guide 35

8 Caveats 36

9 Acknowledgements 36

1

1 IntroductionThis package provides an interface to embed in the rst place interactive Flash (SWF)and 3D objects (Adobe U3D amp PRC) into PDF documents Video and audio les orstreams in the popular MP4 FLV and MP3 formats can be embedded as well Howevera media player Flash component is required for playback as will be explained shortlyPlayback of multimedia les uses Adobe Flash Player which was bundled with AdobeReader 9 and 10 versions Unfortunately beginning with Adobe Reader 11 it must beinstalled as a separate plug-in

Among the supported media types video and sound les require an additional Flash(SWF) application for playback which must be either embedded into the PDF orloaded at runtime from the internet There are numerous such players both open-source and commercial available on the internet One of them is the highly cong-urable open-source lsquoStrobeMediaPlaybackswfrsquo [1 ] maintained by Adobe and hostedon SourceForgenet Package lsquomedia9rsquo comes with an enhanced version of lsquoStrobe-MediaPlaybackswfrsquo In addition two simple players for video and audio lsquoVPlayerswfrsquoand lsquoAPlayerswfrsquo are included which can be used instead They provide sucientfunctionality for playing embedded les and streamed media

There is yet another player bundled with lsquomedia9rsquo It is a simple image gallery viewercalled lsquoSlideShowswfrsquo which can display collections of embedded and remote imagesin the PNG JPEG and GIF le formats Remote images are downloaded at viewingtime and can be congured to be refreshed at denite time intervals

Flash Player supports the ecient H264 codec for video compression MP4H264 videoles can be encoded from existing video les and from numbered bitmap sequencesusing the ffmpeg (httpffmpegorg ) or avconv (httplibavorg ) commandline tools (Libav is a fork from the FFmpeg code) In order to allow for precise seekingwithin video les it is necessary to encode them with a sucient number of key framesThe command line for recoding an existing video le videoavi into videomp4reads (one line ffmpeg can be substituted with avconv)

ffmpeg -i videoavi -vf scale=trunc(iw2)2trunc(ih2)2-cv libx264 -profilev high -pix_fmt yuv420p-g 30 -r 30 videomp4

From a sequence frame-0png frame-1png of bitmap les an MP4 video isproduced by

ffmpeg -i frame-dpng -vf scale=trunc(iw2)2trunc(ih2)2-cv libx264 -profilev high -pix_fmt yuv420p-g 30 -r 30 videomp4

Both examples insert a key frame (option lsquo-grsquo) at every second since the frame rateis set to 30 fps The video encoder requires even pixel numbers in both dimensionswhich is ensured by adding lsquo-vf scale=rsquo to the option list

Note lsquomedia9rsquo package replaces the now obsolete lsquomovie15rsquo package lsquomedia9rsquo is basedon the RichMedia Annotation (Annotations are the interactive elements in a documentin PDF specication parlance) an Adobe addition to the PDF specication [2 ] whilelsquomovie15rsquo uses the old multimedia framework (lsquoScreen Annotationrsquo) of pre-9 Readerswhich depends on third-party plug-ins and which does not support recent media leformats

2

Package lsquomedia9rsquo supports the usual PDF making workows i e pdfLATEX LuaLATEXLATEXrarr dvipsrarr ps2pdfDistiller and (X E)LATEXrarr (x)dvipdfmx

The nal PDF can be viewed in current Adobe Readers on MS Windows and otherplatforms On Unix platforms including Linux however support of Flash video andsound was discontinued at Reader version 942 probably for security reasons PDFdocuments which target Adobe Reader 941 for Linux should use lsquoVPlayer9swfrsquo andlsquoAPlayer9swfrsquo (also included in the lsquomedia9rsquo package) These media player componentsare compatible with the older Flash Player 9 plugin that is bundled with the Readerfor Linux Recent versions of Foxit PDF Reader which is available on the Windowsplatform are known to render embedded Flash video and audio content Foxit alsouses Adobe Flash Player plugin On tablets and phones running Android or iOS ezPDFReader was reported to play video and sound les embedded with lsquomedia9rsquo

2 Requirementsl3kernel (LATEX package) version ge 20190215

l3packages (LATEX package) version ge 20181017

pdfTEX version ge 130

Ghostscript version ge 831 or Adobe Distiller for PS to PDF conversion

dvipdfmx version ge 20120420 for DVI to PDF conversion

Adobe Reader version ge 9 but not greater than 941 on Linux Foxit Reader (Flashvideo audio)

Adobe Flash Player plugin for Firefox

3 InstallationMiKTEX and TEXLive users should run the package manager for installation andupdates

Otherwise a manual installation into the local TeX-Directory-Structure (TDS) rootdirectory is done along the following steps

1 Download the TDS compliant package le lsquomedia9tdszip rsquo from CTAN

2 Find the local TDS root directory by runningkpsewhich -var-value TEXMFLOCAL

on the command line The local TDS root directory is intended for packages thatare not maintained by the TEXLive package manager

3 Unzip lsquomedia9tdsziprsquo into the local TDS root directory previously foundDepending on the location of this directory you may need to be logged in asRootAdministrator

4 After installation update the lename database by running lsquotexhashrsquo on thecommand line Again RootAdministrator privileges may be required

For updating the package repeat the steps given above

3

4 Using the packageInvoke the package by putting the line

usepackage[ltpackage optionsgt]media9

to the preamble of your document i e somewhere between documentclass andbegindocument

lsquomedia9rsquo honours the package options

dvipdfmxxetexbigfilesdraftfinalplaybutton=noplaybuttonactivate=deactivate=windowed=transparentpasscontextattachfiles3Dplaytype=3Dplaycount=3Dplayspeed=3Dtoolbar3Dnavpane3Dpartsattrs=3Dmenu3Dbg=3Dlights=3Drender=

Except for lsquodvipdfmxrsquo lsquoxetexrsquo and lsquobigfilesrsquo the options above are also available(among others) as command options and will be explained shortly However if used aspackage options they have global scope taking eect on all embedded media in thedocument In turn command options locally override global settings Options withoutan argument are boolean options and can be negated by appending lsquo=falsersquo

X ELATEX will be auto-detected Therefore package option lsquoxetexrsquo is optional Howeverin the case of dvipdfmx package option lsquodvipdfmxrsquo is mandatory because it cannotbe auto-detected

If PDF is generated via DVI and Postscript by the command sequence latexrarr dvipsrarr ps2pdf dvips option lsquo-Ppdfrsquo should not be set when converting theintermediate DVI into Postscript If you cannot do without put lsquo-D 1200rsquo after lsquo-Ppdfrsquoon the command line Users of LATEX-aware text editors with menu-driven toolchaininvocation such as TEXnicCenter should check the conguration of the dvips call

Option lsquobigfilesrsquo is only relevant for the latexrarr dvipsrarr ps2pdf workow Itmay be needed if large media les cause latex to abort with error lsquoTeX capacityexceededrsquo See Sect 8

4

5 The user interfacePackage lsquomedia9rsquo provides commands for media inclusion (includemedia) andinsertion of media control buttons (mediabutton) The latter is introduced in Sect53

51 Media inclusionincludemedia[ltoptionsgt]ltposter textgt

ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegt

The last argument ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegtis the main interactive application to be inserted into the PDF In the case of Flashthis can be a local SWF le or a URL such as a YouTube video player A local lewill become part of the nal PDF le while Flash content from a URL requires aninternet connection when the user activates it in Adobe Reader A URL must be fullyqualied i e starting with either lsquohttp[s]rsquo or lsquoftprsquo As for 3D content AdobeReader only supports U3D or PRC les embedded in the PDF they cannot be loadedor streamed during runtime The most frequent use of includemedia will likelybe embedding video or sound les for playback in Adobe Reader For this we needsome media player which is an SWF le we embed as our main application It will becongured to load upon activation a particular video or sound le that was embeddedas a resource into the PDF or is to be streamed from the internet This will be shownlater Note that a local le (main application or resource) will only once be physicallyembedded in order to keep the nal PDF le size small If the same le (identied byMD5 checksum) appears in other includemedia commands only a reference willbe inserted that points to the same storage location in the PDF

Argument ltposter textgt denes the size of the rectangular region of the docu-ment page in which the media will be displayed Moreover ltposter textgt willbe shown in case the media has not been activated ltposter textgt can be any-thing that LATEX can typeset such as an includegraphics command serving as aposter image a PGFTikZPSTricks inline graphics or just ordinary text Alternativelyltposter textgt can be left blank in which case the size of the media rectangle shouldbe set with options lsquowidthrsquo and lsquoheightrsquo If a non-zero size ltposter textgt wasprovided it can be resized using any combination of options lsquowidthrsquo lsquoheightrsquo orlsquototalheightrsquo lsquokeepaspectratiorsquo and lsquoscalersquo

A list of directories where TEX searches for media and resource les can be set-up bymeans of

addmediapathltdirectorygt

This command appends one directory at a time to the search list To specify moredirectories just use it repeatedly The path separator is always lsquorsquo independent fromthe operating system

The following section explains all command options provided They are passed tothe media inclusion command as a comma separated list enclosed in a pair of squarebrackets

5

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 2: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

1 IntroductionThis package provides an interface to embed in the rst place interactive Flash (SWF)and 3D objects (Adobe U3D amp PRC) into PDF documents Video and audio les orstreams in the popular MP4 FLV and MP3 formats can be embedded as well Howevera media player Flash component is required for playback as will be explained shortlyPlayback of multimedia les uses Adobe Flash Player which was bundled with AdobeReader 9 and 10 versions Unfortunately beginning with Adobe Reader 11 it must beinstalled as a separate plug-in

Among the supported media types video and sound les require an additional Flash(SWF) application for playback which must be either embedded into the PDF orloaded at runtime from the internet There are numerous such players both open-source and commercial available on the internet One of them is the highly cong-urable open-source lsquoStrobeMediaPlaybackswfrsquo [1 ] maintained by Adobe and hostedon SourceForgenet Package lsquomedia9rsquo comes with an enhanced version of lsquoStrobe-MediaPlaybackswfrsquo In addition two simple players for video and audio lsquoVPlayerswfrsquoand lsquoAPlayerswfrsquo are included which can be used instead They provide sucientfunctionality for playing embedded les and streamed media

There is yet another player bundled with lsquomedia9rsquo It is a simple image gallery viewercalled lsquoSlideShowswfrsquo which can display collections of embedded and remote imagesin the PNG JPEG and GIF le formats Remote images are downloaded at viewingtime and can be congured to be refreshed at denite time intervals

Flash Player supports the ecient H264 codec for video compression MP4H264 videoles can be encoded from existing video les and from numbered bitmap sequencesusing the ffmpeg (httpffmpegorg ) or avconv (httplibavorg ) commandline tools (Libav is a fork from the FFmpeg code) In order to allow for precise seekingwithin video les it is necessary to encode them with a sucient number of key framesThe command line for recoding an existing video le videoavi into videomp4reads (one line ffmpeg can be substituted with avconv)

ffmpeg -i videoavi -vf scale=trunc(iw2)2trunc(ih2)2-cv libx264 -profilev high -pix_fmt yuv420p-g 30 -r 30 videomp4

From a sequence frame-0png frame-1png of bitmap les an MP4 video isproduced by

ffmpeg -i frame-dpng -vf scale=trunc(iw2)2trunc(ih2)2-cv libx264 -profilev high -pix_fmt yuv420p-g 30 -r 30 videomp4

Both examples insert a key frame (option lsquo-grsquo) at every second since the frame rateis set to 30 fps The video encoder requires even pixel numbers in both dimensionswhich is ensured by adding lsquo-vf scale=rsquo to the option list

Note lsquomedia9rsquo package replaces the now obsolete lsquomovie15rsquo package lsquomedia9rsquo is basedon the RichMedia Annotation (Annotations are the interactive elements in a documentin PDF specication parlance) an Adobe addition to the PDF specication [2 ] whilelsquomovie15rsquo uses the old multimedia framework (lsquoScreen Annotationrsquo) of pre-9 Readerswhich depends on third-party plug-ins and which does not support recent media leformats

2

Package lsquomedia9rsquo supports the usual PDF making workows i e pdfLATEX LuaLATEXLATEXrarr dvipsrarr ps2pdfDistiller and (X E)LATEXrarr (x)dvipdfmx

The nal PDF can be viewed in current Adobe Readers on MS Windows and otherplatforms On Unix platforms including Linux however support of Flash video andsound was discontinued at Reader version 942 probably for security reasons PDFdocuments which target Adobe Reader 941 for Linux should use lsquoVPlayer9swfrsquo andlsquoAPlayer9swfrsquo (also included in the lsquomedia9rsquo package) These media player componentsare compatible with the older Flash Player 9 plugin that is bundled with the Readerfor Linux Recent versions of Foxit PDF Reader which is available on the Windowsplatform are known to render embedded Flash video and audio content Foxit alsouses Adobe Flash Player plugin On tablets and phones running Android or iOS ezPDFReader was reported to play video and sound les embedded with lsquomedia9rsquo

2 Requirementsl3kernel (LATEX package) version ge 20190215

l3packages (LATEX package) version ge 20181017

pdfTEX version ge 130

Ghostscript version ge 831 or Adobe Distiller for PS to PDF conversion

dvipdfmx version ge 20120420 for DVI to PDF conversion

Adobe Reader version ge 9 but not greater than 941 on Linux Foxit Reader (Flashvideo audio)

Adobe Flash Player plugin for Firefox

3 InstallationMiKTEX and TEXLive users should run the package manager for installation andupdates

Otherwise a manual installation into the local TeX-Directory-Structure (TDS) rootdirectory is done along the following steps

1 Download the TDS compliant package le lsquomedia9tdszip rsquo from CTAN

2 Find the local TDS root directory by runningkpsewhich -var-value TEXMFLOCAL

on the command line The local TDS root directory is intended for packages thatare not maintained by the TEXLive package manager

3 Unzip lsquomedia9tdsziprsquo into the local TDS root directory previously foundDepending on the location of this directory you may need to be logged in asRootAdministrator

4 After installation update the lename database by running lsquotexhashrsquo on thecommand line Again RootAdministrator privileges may be required

For updating the package repeat the steps given above

3

4 Using the packageInvoke the package by putting the line

usepackage[ltpackage optionsgt]media9

to the preamble of your document i e somewhere between documentclass andbegindocument

lsquomedia9rsquo honours the package options

dvipdfmxxetexbigfilesdraftfinalplaybutton=noplaybuttonactivate=deactivate=windowed=transparentpasscontextattachfiles3Dplaytype=3Dplaycount=3Dplayspeed=3Dtoolbar3Dnavpane3Dpartsattrs=3Dmenu3Dbg=3Dlights=3Drender=

Except for lsquodvipdfmxrsquo lsquoxetexrsquo and lsquobigfilesrsquo the options above are also available(among others) as command options and will be explained shortly However if used aspackage options they have global scope taking eect on all embedded media in thedocument In turn command options locally override global settings Options withoutan argument are boolean options and can be negated by appending lsquo=falsersquo

X ELATEX will be auto-detected Therefore package option lsquoxetexrsquo is optional Howeverin the case of dvipdfmx package option lsquodvipdfmxrsquo is mandatory because it cannotbe auto-detected

If PDF is generated via DVI and Postscript by the command sequence latexrarr dvipsrarr ps2pdf dvips option lsquo-Ppdfrsquo should not be set when converting theintermediate DVI into Postscript If you cannot do without put lsquo-D 1200rsquo after lsquo-Ppdfrsquoon the command line Users of LATEX-aware text editors with menu-driven toolchaininvocation such as TEXnicCenter should check the conguration of the dvips call

Option lsquobigfilesrsquo is only relevant for the latexrarr dvipsrarr ps2pdf workow Itmay be needed if large media les cause latex to abort with error lsquoTeX capacityexceededrsquo See Sect 8

4

5 The user interfacePackage lsquomedia9rsquo provides commands for media inclusion (includemedia) andinsertion of media control buttons (mediabutton) The latter is introduced in Sect53

51 Media inclusionincludemedia[ltoptionsgt]ltposter textgt

ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegt

The last argument ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegtis the main interactive application to be inserted into the PDF In the case of Flashthis can be a local SWF le or a URL such as a YouTube video player A local lewill become part of the nal PDF le while Flash content from a URL requires aninternet connection when the user activates it in Adobe Reader A URL must be fullyqualied i e starting with either lsquohttp[s]rsquo or lsquoftprsquo As for 3D content AdobeReader only supports U3D or PRC les embedded in the PDF they cannot be loadedor streamed during runtime The most frequent use of includemedia will likelybe embedding video or sound les for playback in Adobe Reader For this we needsome media player which is an SWF le we embed as our main application It will becongured to load upon activation a particular video or sound le that was embeddedas a resource into the PDF or is to be streamed from the internet This will be shownlater Note that a local le (main application or resource) will only once be physicallyembedded in order to keep the nal PDF le size small If the same le (identied byMD5 checksum) appears in other includemedia commands only a reference willbe inserted that points to the same storage location in the PDF

Argument ltposter textgt denes the size of the rectangular region of the docu-ment page in which the media will be displayed Moreover ltposter textgt willbe shown in case the media has not been activated ltposter textgt can be any-thing that LATEX can typeset such as an includegraphics command serving as aposter image a PGFTikZPSTricks inline graphics or just ordinary text Alternativelyltposter textgt can be left blank in which case the size of the media rectangle shouldbe set with options lsquowidthrsquo and lsquoheightrsquo If a non-zero size ltposter textgt wasprovided it can be resized using any combination of options lsquowidthrsquo lsquoheightrsquo orlsquototalheightrsquo lsquokeepaspectratiorsquo and lsquoscalersquo

A list of directories where TEX searches for media and resource les can be set-up bymeans of

addmediapathltdirectorygt

This command appends one directory at a time to the search list To specify moredirectories just use it repeatedly The path separator is always lsquorsquo independent fromthe operating system

The following section explains all command options provided They are passed tothe media inclusion command as a comma separated list enclosed in a pair of squarebrackets

5

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 3: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Package lsquomedia9rsquo supports the usual PDF making workows i e pdfLATEX LuaLATEXLATEXrarr dvipsrarr ps2pdfDistiller and (X E)LATEXrarr (x)dvipdfmx

The nal PDF can be viewed in current Adobe Readers on MS Windows and otherplatforms On Unix platforms including Linux however support of Flash video andsound was discontinued at Reader version 942 probably for security reasons PDFdocuments which target Adobe Reader 941 for Linux should use lsquoVPlayer9swfrsquo andlsquoAPlayer9swfrsquo (also included in the lsquomedia9rsquo package) These media player componentsare compatible with the older Flash Player 9 plugin that is bundled with the Readerfor Linux Recent versions of Foxit PDF Reader which is available on the Windowsplatform are known to render embedded Flash video and audio content Foxit alsouses Adobe Flash Player plugin On tablets and phones running Android or iOS ezPDFReader was reported to play video and sound les embedded with lsquomedia9rsquo

2 Requirementsl3kernel (LATEX package) version ge 20190215

l3packages (LATEX package) version ge 20181017

pdfTEX version ge 130

Ghostscript version ge 831 or Adobe Distiller for PS to PDF conversion

dvipdfmx version ge 20120420 for DVI to PDF conversion

Adobe Reader version ge 9 but not greater than 941 on Linux Foxit Reader (Flashvideo audio)

Adobe Flash Player plugin for Firefox

3 InstallationMiKTEX and TEXLive users should run the package manager for installation andupdates

Otherwise a manual installation into the local TeX-Directory-Structure (TDS) rootdirectory is done along the following steps

1 Download the TDS compliant package le lsquomedia9tdszip rsquo from CTAN

2 Find the local TDS root directory by runningkpsewhich -var-value TEXMFLOCAL

on the command line The local TDS root directory is intended for packages thatare not maintained by the TEXLive package manager

3 Unzip lsquomedia9tdsziprsquo into the local TDS root directory previously foundDepending on the location of this directory you may need to be logged in asRootAdministrator

4 After installation update the lename database by running lsquotexhashrsquo on thecommand line Again RootAdministrator privileges may be required

For updating the package repeat the steps given above

3

4 Using the packageInvoke the package by putting the line

usepackage[ltpackage optionsgt]media9

to the preamble of your document i e somewhere between documentclass andbegindocument

lsquomedia9rsquo honours the package options

dvipdfmxxetexbigfilesdraftfinalplaybutton=noplaybuttonactivate=deactivate=windowed=transparentpasscontextattachfiles3Dplaytype=3Dplaycount=3Dplayspeed=3Dtoolbar3Dnavpane3Dpartsattrs=3Dmenu3Dbg=3Dlights=3Drender=

Except for lsquodvipdfmxrsquo lsquoxetexrsquo and lsquobigfilesrsquo the options above are also available(among others) as command options and will be explained shortly However if used aspackage options they have global scope taking eect on all embedded media in thedocument In turn command options locally override global settings Options withoutan argument are boolean options and can be negated by appending lsquo=falsersquo

X ELATEX will be auto-detected Therefore package option lsquoxetexrsquo is optional Howeverin the case of dvipdfmx package option lsquodvipdfmxrsquo is mandatory because it cannotbe auto-detected

If PDF is generated via DVI and Postscript by the command sequence latexrarr dvipsrarr ps2pdf dvips option lsquo-Ppdfrsquo should not be set when converting theintermediate DVI into Postscript If you cannot do without put lsquo-D 1200rsquo after lsquo-Ppdfrsquoon the command line Users of LATEX-aware text editors with menu-driven toolchaininvocation such as TEXnicCenter should check the conguration of the dvips call

Option lsquobigfilesrsquo is only relevant for the latexrarr dvipsrarr ps2pdf workow Itmay be needed if large media les cause latex to abort with error lsquoTeX capacityexceededrsquo See Sect 8

4

5 The user interfacePackage lsquomedia9rsquo provides commands for media inclusion (includemedia) andinsertion of media control buttons (mediabutton) The latter is introduced in Sect53

51 Media inclusionincludemedia[ltoptionsgt]ltposter textgt

ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegt

The last argument ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegtis the main interactive application to be inserted into the PDF In the case of Flashthis can be a local SWF le or a URL such as a YouTube video player A local lewill become part of the nal PDF le while Flash content from a URL requires aninternet connection when the user activates it in Adobe Reader A URL must be fullyqualied i e starting with either lsquohttp[s]rsquo or lsquoftprsquo As for 3D content AdobeReader only supports U3D or PRC les embedded in the PDF they cannot be loadedor streamed during runtime The most frequent use of includemedia will likelybe embedding video or sound les for playback in Adobe Reader For this we needsome media player which is an SWF le we embed as our main application It will becongured to load upon activation a particular video or sound le that was embeddedas a resource into the PDF or is to be streamed from the internet This will be shownlater Note that a local le (main application or resource) will only once be physicallyembedded in order to keep the nal PDF le size small If the same le (identied byMD5 checksum) appears in other includemedia commands only a reference willbe inserted that points to the same storage location in the PDF

Argument ltposter textgt denes the size of the rectangular region of the docu-ment page in which the media will be displayed Moreover ltposter textgt willbe shown in case the media has not been activated ltposter textgt can be any-thing that LATEX can typeset such as an includegraphics command serving as aposter image a PGFTikZPSTricks inline graphics or just ordinary text Alternativelyltposter textgt can be left blank in which case the size of the media rectangle shouldbe set with options lsquowidthrsquo and lsquoheightrsquo If a non-zero size ltposter textgt wasprovided it can be resized using any combination of options lsquowidthrsquo lsquoheightrsquo orlsquototalheightrsquo lsquokeepaspectratiorsquo and lsquoscalersquo

A list of directories where TEX searches for media and resource les can be set-up bymeans of

addmediapathltdirectorygt

This command appends one directory at a time to the search list To specify moredirectories just use it repeatedly The path separator is always lsquorsquo independent fromthe operating system

The following section explains all command options provided They are passed tothe media inclusion command as a comma separated list enclosed in a pair of squarebrackets

5

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 4: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

4 Using the packageInvoke the package by putting the line

usepackage[ltpackage optionsgt]media9

to the preamble of your document i e somewhere between documentclass andbegindocument

lsquomedia9rsquo honours the package options

dvipdfmxxetexbigfilesdraftfinalplaybutton=noplaybuttonactivate=deactivate=windowed=transparentpasscontextattachfiles3Dplaytype=3Dplaycount=3Dplayspeed=3Dtoolbar3Dnavpane3Dpartsattrs=3Dmenu3Dbg=3Dlights=3Drender=

Except for lsquodvipdfmxrsquo lsquoxetexrsquo and lsquobigfilesrsquo the options above are also available(among others) as command options and will be explained shortly However if used aspackage options they have global scope taking eect on all embedded media in thedocument In turn command options locally override global settings Options withoutan argument are boolean options and can be negated by appending lsquo=falsersquo

X ELATEX will be auto-detected Therefore package option lsquoxetexrsquo is optional Howeverin the case of dvipdfmx package option lsquodvipdfmxrsquo is mandatory because it cannotbe auto-detected

If PDF is generated via DVI and Postscript by the command sequence latexrarr dvipsrarr ps2pdf dvips option lsquo-Ppdfrsquo should not be set when converting theintermediate DVI into Postscript If you cannot do without put lsquo-D 1200rsquo after lsquo-Ppdfrsquoon the command line Users of LATEX-aware text editors with menu-driven toolchaininvocation such as TEXnicCenter should check the conguration of the dvips call

Option lsquobigfilesrsquo is only relevant for the latexrarr dvipsrarr ps2pdf workow Itmay be needed if large media les cause latex to abort with error lsquoTeX capacityexceededrsquo See Sect 8

4

5 The user interfacePackage lsquomedia9rsquo provides commands for media inclusion (includemedia) andinsertion of media control buttons (mediabutton) The latter is introduced in Sect53

51 Media inclusionincludemedia[ltoptionsgt]ltposter textgt

ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegt

The last argument ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegtis the main interactive application to be inserted into the PDF In the case of Flashthis can be a local SWF le or a URL such as a YouTube video player A local lewill become part of the nal PDF le while Flash content from a URL requires aninternet connection when the user activates it in Adobe Reader A URL must be fullyqualied i e starting with either lsquohttp[s]rsquo or lsquoftprsquo As for 3D content AdobeReader only supports U3D or PRC les embedded in the PDF they cannot be loadedor streamed during runtime The most frequent use of includemedia will likelybe embedding video or sound les for playback in Adobe Reader For this we needsome media player which is an SWF le we embed as our main application It will becongured to load upon activation a particular video or sound le that was embeddedas a resource into the PDF or is to be streamed from the internet This will be shownlater Note that a local le (main application or resource) will only once be physicallyembedded in order to keep the nal PDF le size small If the same le (identied byMD5 checksum) appears in other includemedia commands only a reference willbe inserted that points to the same storage location in the PDF

Argument ltposter textgt denes the size of the rectangular region of the docu-ment page in which the media will be displayed Moreover ltposter textgt willbe shown in case the media has not been activated ltposter textgt can be any-thing that LATEX can typeset such as an includegraphics command serving as aposter image a PGFTikZPSTricks inline graphics or just ordinary text Alternativelyltposter textgt can be left blank in which case the size of the media rectangle shouldbe set with options lsquowidthrsquo and lsquoheightrsquo If a non-zero size ltposter textgt wasprovided it can be resized using any combination of options lsquowidthrsquo lsquoheightrsquo orlsquototalheightrsquo lsquokeepaspectratiorsquo and lsquoscalersquo

A list of directories where TEX searches for media and resource les can be set-up bymeans of

addmediapathltdirectorygt

This command appends one directory at a time to the search list To specify moredirectories just use it repeatedly The path separator is always lsquorsquo independent fromthe operating system

The following section explains all command options provided They are passed tothe media inclusion command as a comma separated list enclosed in a pair of squarebrackets

5

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 5: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

5 The user interfacePackage lsquomedia9rsquo provides commands for media inclusion (includemedia) andinsertion of media control buttons (mediabutton) The latter is introduced in Sect53

51 Media inclusionincludemedia[ltoptionsgt]ltposter textgt

ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegt

The last argument ltmain Flash (SWF) file or URL | 3D (PRC U3D) filegtis the main interactive application to be inserted into the PDF In the case of Flashthis can be a local SWF le or a URL such as a YouTube video player A local lewill become part of the nal PDF le while Flash content from a URL requires aninternet connection when the user activates it in Adobe Reader A URL must be fullyqualied i e starting with either lsquohttp[s]rsquo or lsquoftprsquo As for 3D content AdobeReader only supports U3D or PRC les embedded in the PDF they cannot be loadedor streamed during runtime The most frequent use of includemedia will likelybe embedding video or sound les for playback in Adobe Reader For this we needsome media player which is an SWF le we embed as our main application It will becongured to load upon activation a particular video or sound le that was embeddedas a resource into the PDF or is to be streamed from the internet This will be shownlater Note that a local le (main application or resource) will only once be physicallyembedded in order to keep the nal PDF le size small If the same le (identied byMD5 checksum) appears in other includemedia commands only a reference willbe inserted that points to the same storage location in the PDF

Argument ltposter textgt denes the size of the rectangular region of the docu-ment page in which the media will be displayed Moreover ltposter textgt willbe shown in case the media has not been activated ltposter textgt can be any-thing that LATEX can typeset such as an includegraphics command serving as aposter image a PGFTikZPSTricks inline graphics or just ordinary text Alternativelyltposter textgt can be left blank in which case the size of the media rectangle shouldbe set with options lsquowidthrsquo and lsquoheightrsquo If a non-zero size ltposter textgt wasprovided it can be resized using any combination of options lsquowidthrsquo lsquoheightrsquo orlsquototalheightrsquo lsquokeepaspectratiorsquo and lsquoscalersquo

A list of directories where TEX searches for media and resource les can be set-up bymeans of

addmediapathltdirectorygt

This command appends one directory at a time to the search list To specify moredirectories just use it repeatedly The path separator is always lsquorsquo independent fromthe operating system

The following section explains all command options provided They are passed tothe media inclusion command as a comma separated list enclosed in a pair of squarebrackets

5

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 6: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

52 Command optionsA subset of the command options (see Sect 4 ) can also be used as package optionswhich lets them apply to all embedded media Some of the options listed here aremeaningful only for a specic media type (either Flash or 3D) which will be notedexplicitly if not obvious Dedicated sections covering Flash video and sound as well as3D inclusion will follow later on in this document

label=ltlabel textgt

The media annotation is given a label ltlabel textgt which should be unique La-belled media annotations can be targeted by the media actions of a control button(see description of the mediabutton command in Sect 53 ) Moreover a referenceto the RichMedia Annotation object (of type lsquoAnnotRichMediarsquo) is assigned to theJavaScript variable annotRM[ltlabel textgt] in order to facilitate its access inJavaScript Note that the JavaScript reference is known only after the rst opening ofthe page containing the media

width=lth-sizegtheight=ltv-sizegt | totalheight=ltv-sizegtkeepaspectratio

Resize the media playback area ltposter textgt if provided is squeezed or stretchedaccordingly If only one of lsquowidthrsquo or lsquo[total]heightrsquo is given the other dimen-sion is scaled to maintain the aspect ratio of ltposter textgt If both lsquowidthrsquo andlsquo[total]heightrsquo are given together with lsquokeepaspectratiorsquo ltposter textgt isresized to t within lth-sizegt and ltv-sizegt while maintaining its original aspectratio Any valid TEX dimension is acceptable for lth-sizegt and ltv-sizegt In additionthe length commands width height depth and totalheight can be used torefer to the original dimensions of ltposter textgt

scale=ltfactorgt

Scales the playback area by ltfactorgt

addresource=ltlocal filegtaddresource=ltanother local filegt

Every invocation of this option embeds another local le that is required to run themain Flash application or 3D le (last argument of includemedia) Typically thisoption is used to embed video les media player skins XML les (such as databases)additional objects to appear in a 3D scene etc If an already embedded le is needed inanother includemedia command this option must be given there again Howeverthe le in question will only once be physically embedded in order to keep the PDFle small

flashvars=ltsome_var=some_valampanother_var=another_valampgt

(Flash only) Usually Flash applications can be congured via ActionScript (AS) vari-ables the programmer of the application has made visible from outside A typical usewould be to set the video source of a media player to point to an embedded MP4 le orto a live stream or to set the speaker volume for playback of an MP3 le The argumentof the flashvars option is a list of ltAS variablegt=ltvaluegt pairs separated by lsquoamprsquoand enclosed in a pair of braces ()

6

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 7: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Note If a variable is to be set to point to an embedded resource the value of thevariable must be given in exactly the same way as with the lsquoaddresourcersquo optionOtherwise the name of the embedded le cannot be resolved For example

addresource=pathtovideomp4

implies

flashvars=vid=pathtovideomp4amp

if for a particular media player the video source is set through ActionScript variablelsquovidrsquo

(Note for 3D) Resource les used in 3D scenes cannot be loaded by means of Action-Script variables This must be done by 3D JavaScript during activation of the 3D scenein the Reader 3D JavaScript can be attached using option lsquoadd3Djscriptrsquo see below

attachfiles

If set embedded les can be downloaded from the PDF via the Attachments navigationpane in the Reader

activate=onclick | pageopen | pagevisible

Decides on how to activate the media annotation lsquoactivate=onclickrsquo is defaultbehaviour and does not need be given explicitly embedded media is activated when theuser clicks on it or by a JavaScript It is recommended to provide a poster image with theltposter textgt argument in that case lsquopageopenrsquo and lsquopagevisiblersquo automaticallyactivate the media when the page becomes visible lsquopagevisiblersquo is better for two-upand continuous page display

deactivate=onclick | pageclose | pageinvisible

Decides on how to de-activate the media annotation lsquodeactivate=pageclosersquo isdefault behaviour and does not need be given explicitly media is automatically de-activated when the user leaves the page containing the media lsquopageinvisiblersquo issimilar but may be better for two-up and continuous page display Setting lsquodeactivate=onclickrsquo requires user interaction for de-activating the media either by right-clickand chosing lsquoDisable Contentrsquo or by a JavaScript

draftfinal

With lsquodraftrsquo the media is not embedded Instead a box is inserted that has thedimensions of ltposter textgt subject to the resizing options lsquowidthrsquo lsquoheightrsquolsquototalheightrsquo and lsquoscalersquo Option lsquofinalrsquo does the opposite as it forces the media tobe embedded Both options can be used to reduce compilation time during authoringof a document To get the most out of them it is recommended to set lsquodraftrsquo globallyas a package or class option and to set lsquofinalrsquo locally as a command option of themedia annotation that is currently worked on After the document has been nishedthe global lsquodraftrsquo option can be removed

playbutton[= fancy | plain | none]noplaybutton

By default a transparent play button is laid over the inactive media annotation to drawthe readerrsquos attention to the embedded multimedia content It is provided in two ver-

7

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 8: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

sions lsquofancyrsquo and lsquoplainrsquo but only lsquoplainrsquo is available in the X ELATEX workow Thedefault setting is to try the lsquofancyrsquo version lsquonoplaybuttonrsquo or lsquoplaybutton=nonersquodisable the play button overlay

windowed[= false | [ltwidthgtxltheightgt][ltpositiongt] ]

The media is played in a oating window instead of being played in an embedded fash-ion The oating window size is specied via the optional argument ltwidthgtxltheightgtwhere ltwidthgt and ltheightgt are given in pixels (integer numbers without unit) Ifthe size is not given a default size is guessed from the annotation size Optionally theposition of the oating window on the screen can be specied through ltpositiongtwhere ltpositiongt may assume one of lsquotlrsquo lsquoclrsquo lsquoblrsquo lsquobcrsquo lsquobrrsquo lsquocrrsquo lsquotrrsquo lsquotcrsquo or lsquoccrsquoThe position speciers have the following meaning tl tc tr

cl cc crbl bc br

Default window position is lsquoccrsquo that is centred on the screen lsquofalsersquo can be set tooverride a global setting via package options

transparent

Indicates whether underlying page content is visible through transparent areas of theembedded media Default is lsquotransparent=falsersquo media artwork is drawn over anopaque background prior to composition over the page content

passcontext

(Flash only) If set user right-clicks are passed through to the context menu of theembedded Flash application replacing the default Adobe Reader context menu Usefulfor cases where the Flash programmer provided additional functionality through thecontext menu of his application

3Dtoolbar

Indicates whether a 3D toolbar should be shown in the Reader on top of the embedded3D model

3Dnavpane

If set the 3D navigation pane displaying the 3D Model Tree becomes visible in theReader when the content is initially activated

3Dcoo=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify the positional vector minusminusminusrarrCOO of the centre of orbit of the virtualcamera Real numbers in xed and oating point notation are accepted

3Dc2c=ltxgt ltygt ltzgt

ltxgt ltygt ltzgt specify a direction vector minusminusminusrarrC2C of arbitrary length originating in thecentre of orbit and pointing to the virtual camera Real numbers in xed and oatingpoint notation are accepted

3Droll=ltrollgt

Prescribes an initial camera roll around the optical axis (in clockwise direction ifltrollgt is greater that zero) measured in degrees and given as xed or oating pointreal number

8

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 9: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

3Dc2w=lt12 element camera-to-world matrixgt

This option directly sets the camera-to-world transformation matrix according to thePDF specication This is an expert option to be used instead of the lsquo3Dc2crsquo lsquo3Dcoorsquoand lsquo3Drollrsquo options Only xed point real numbers are accepted

3Dpsob=Min | Max | W | H

Expert option which directly sets either the PS entry in the case of perspectiveprojection or the OB entry in the case of orthographic projection to one of the fourpossible values Default value is Min

3Droo=ltrgt

ltrgt is a positive xed or oating point number specifying the radius of orbit ROO ofthe virtual camera Good values can be found by means of the lsquo3Dmenursquo option

3Daac=ltanglegt

This option sets the aperture angle of the camera measured in degrees for the per-spective view mode Fixed and oating point real numbers between 0 and 180 areadmissible A sensible value of 30 is pre-set by default Larger values can be usedto achieve wide-angle or sh-eye eects See example 10 in section 71 This optionexcludes the use of the lsquo3Dorthorsquo option

3Dortho[=ltorthographic scaling factorgt]

Switches from the default perspective to orthographic view mode In orthographic viewthe 3D object is parallelly projected onto the virtual camera chip The projected imageis scaled by ltorthographic scaling factorgt before reaching the camera chipdefault value is 1 The optimal value for the scaling factor is given by 1D where D isthe diameter of the smallest enclosing sphere of the 3D object in World coordinate unitsFixed and oating point real numbers are accepted The camera should be positionedoutside the 3D object For this the radius of orbit (option lsquo3Droorsquo) should be greaterthan D2 Good values for orthographic scaling and orbital radius can easily be foundby means of the lsquo3Dmenursquo option Option lsquo3Dorthorsquo excludes the use of the lsquo3Daacrsquooption

3Dmenu

Mainly used during document authoring Adds three entries lsquoGenerate Default ViewrsquolsquoGet Current Viewrsquo and lsquoCross Sectionrsquo to the context (right-click) menu of an activated3D annotation Moreover it allows single parts or part groups of the scene to be scaledtranslated and rotated against the remaining scene objects using the keyboard Theirnew position can be saved in the current view (lsquoGet Current Viewrsquo) At rst parts tobe modied must be highlighted by clicking either into the scene or into the 3D ModelTree (the partrsquos bounding box becomes visible) Then arrow keys let the partspin around the vertical axis and tilt against it In order to spin parts aroundtheir local up-axis keep ctrl pressed while using and Keys X + X Y + Y Z + Z translate the selected part along the World axes and S

+ S scale the part

lsquoGenerate Default Viewrsquo computes optimal camera settings such that the visible partsof the 3D scene t tightly into the viewing area The result is printed formatted as alist of includemedia options into the JavaScript console The calculation is based

9

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 10: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

on the 3D object size and its position in the World coordinate system as well as thecurrent viewing mode (perspective or orthographic)

lsquoCross Sectionrsquo is a toggle switch to add or remove a cross section to or from the currentview If a part of the 3D scene was previously selected the central rotating point ofthe cutting plane is put into the partrsquos centre otherwise into the target point of thecamera The cutting plane can be rotated around the vertical axis and tilted againstits upright position using the arrow keys and Keys X + X Y + Y Z + Z move the cutting plane along the World axes and S

+ S scale its size

lsquoGet Current Viewrsquo writes camera settings any part alterations an optional cross sectionas well as part and scene rendering attributes of the current view into the JavaScriptconsole The output is a readily formatted VIEW section to be inserted into or appendedto a le of predened views See option lsquo3Dviewsrsquo All settings reachable via the lsquoPartOptionsrsquo and lsquoViewing Optionsrsquo context menu items are written to the VIEW section

3Dbg=ltrgt ltggt ltbgt

This option sets the background colour of the 3D scene Only xed point real numbersin the range from 0 to 1 are allowed for the colour components Option lsquotransparentrsquomay not be set at the same time

3Dlights=ltlighting schemegt

Sets the default lighting scheme The following values are honoured lsquoNonersquo lsquoWhitersquolsquoDayrsquo lsquoNightrsquo lsquoHardrsquo lsquoPrimaryrsquo lsquoBluersquo lsquoRedrsquo lsquoCubersquo lsquoCADrsquo lsquoHeadLamprsquo The defaultis to use the lighting scheme as specied within the 3D artwork

3Drender=Solid | Transparent[ltopacitygt] |

Sets the default render mode of the scene The following values are honoured lsquoSolidrsquolsquoSolidWireframersquo lsquoTransparentrsquo lsquoTransparentWireframersquo lsquoBoundingBoxrsquolsquoTransparentBoundingBoxrsquo lsquoTransparentBoundingBoxOutlinersquo lsquoWireframersquolsquoShadedWireframersquo lsquoHiddenWireframersquo lsquoVerticesrsquo lsquoShadedVerticesrsquolsquoSolidOutlinersquo lsquoIllustrationrsquo lsquoShadedIllustrationrsquo Options lsquoTransparentrsquoand lsquoTransparentWireframersquo take an optional value between 0 and 1 that controlsthe opacity of the rendered 3D object

3Dpartsattrs=restore | keep

When the user selects another view from the list of predened views (see optionlsquo3Dviewsrsquo) attributes of individual parts such as opacity visibility render modetranslation in space which all can be set from within the Reader or by means of a leof predened views are reset to their original states as dened in the embedded 3Dle before any new part settings are applied This default behaviour can be overriddenby lsquo3Dpartsattrs=keeprsquo This will preserve current part attributes when the userselects another predened 3D view in the Reader

3Dviews=ltviews filegt

Instead of or in addition to the default view (options lsquo3Dcoorsquo lsquo3Dc2crsquo lsquo3Drollrsquolsquo3Droorsquo lsquo3Daacrsquo lsquo3Dorthorsquo) further named views can be predened in an auxili-ary le ltviews filegt Besides the virtual camera position it is possible to adjust therendering attributes such as visibility and transparency as well as position and scalingof every single part in the 3D scene Moreover background colour and scene lighting

10

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 11: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

can be set individually for every view The additional views can later be selected eitherfrom a drop down list in the tool bar that is associated with the activated 3D object inthe Reader or from the context menu of the 3D object

The le ltviews filegt is structured into view sections one for every view

VIEW[=ltoptional namegt]COO=ltxgt ltygt ltzgtC2C=ltxgt ltygt ltzgtROLL=ltrollgt

C2W=ltcamera-to-world matrixgt instead of COO C2C and ROLLROO=ltroogtAAC=ltaacgt

ORTHO[=ltothographic scaling factorgt] instead of AACBGCOLOR=ltrgt ltggt ltbgtRENDERMODE=ltrender modegtLIGHTS=ltlighting schemegtCROSSSECT

CENTER=ltxgt ltygt ltzgtNORMAL=ltxgt ltygt ltzgtOPACITY=ltcutting plane opacitygtVISIBLE=true | falsePLANECOLOR=ltrgt ltggt ltbgtINTERSECTIONVISIBLE=true | falseINTERSECTIONCOLOR=ltrgt ltggt ltbgt

ENDPARTSATTRS=keepPART=ltpart name as in the Model Tree (required optional if UTF16NAME present)gt

UTF16NAME=ltpart name as hex encoded Unicode stringgtVISIBLE=true | falseOPACITY=ltpart opacitygtRENDERMODE=ltpart render modegtTRANSFORM=lt12 element transformation matrixgt

ENDPART=ltgt

ENDetc

END

VIEW

END

etc

A view section starts with the keyword VIEW optionally followed by a name for theview and ends with the keyword END If no name is given to the view a default one iscreated consisting of lsquoViewrsquo followed by the number of the current VIEW section inthe le A VIEW section may contain optional entries for setting the camera positionand global rendering attributes of the scene a CROSSSECT subsection as well as PART

11

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 12: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

subsections for setting rendering and other attributes of parts individually Table 1

lists the entries in a VIEW section

Part sub-sections are opened by PART=ltpart namegt and closed by END There maybe as many part subsections as there are parts in a 3D scene Table 2 lists the possibleentries in a PART sub-section All entries are optional However a UTF16NAME entry isrecommended as the part name may contain non-ASCII characters The value of theUTF16NAME key is the part name as a hex-encoded Unicode string If UTF16NAME isnot used the part name in the 3D le must be entirely composed of ASCII charactersIn that case ltpart namegt is mandatory and must match the part name as indicatedin the 3D Model Tree of the 3D object (accessible via right-click onto the model inthe Reader) The part can be scaled and repositioned by means of a TRANSFORM entrywhich takes a 12-element transformation matrix as its value Remaining entries in apart sub-section control the visual appearance of the part

A view section may contain at most one CROSSSECT sub-section It inserts a cuttingplane at a denite position and orientation in the 3D space controlled by optionalCENTER and NORMAL entries The appearance characteristics of the cutting plane andthe intersection of the plane with the 3D geometry are controlled by optional OPACITYVISIBLE PLANECOLOR INTERSECTIONVISIBLE INTERSECTIONCOLOR entries SeeTable 3 for explanation

The views le can be commented As usual comments start with the percent sign

To facilitate the creation of a views le option lsquo3Dmenursquo can be added to includemedia(see above) It creates context (right-click) menu entry lsquoGet Current Viewrsquo which out-puts a complete VIEW section corresponding to the current view of the 3D object in theReader including camera position an optional cross section and all part and viewingoptions that can be modied via the 3D toolbar (option lsquo3Dtoolbarrsquo) or the contextmenu of the 3D object (entries lsquoPart Optionsrsquo lsquoViewing Optionsrsquo) Hence apart fromtweaking one or another entry there should be no need for writing views les byhand

3Dplaytype=linear | oscillating

According to the PDF specication embedded keyframe animations can be played intwo ways If set to lsquolinearrsquo keyframe animations are driven linearly from beginningto end while lsquooscillatingrsquo lets the animation play in a forth-and-back manner

3Dplaycount=ltinteger numbergt

A non-negative ltinteger numbergt represents the number of times the animationis played A negative integer indicates that the animation is innitely repeated Thisvalue is ignored if option 3Dplaytype is not set

3Dplayspeed=ltpositive numbergt

This option can be used to adjust the keyframe animation speed A value of lsquo1rsquo corres-ponds to the default speed dened in the 3D le

add3Djscript=lt3D JavaScript filegtadd3Djscript=ltanother 3D JavaScript filegt

Things like animation lighting background of 3D objects etc may also be scriptdriven Every invocation of lsquoadd3Djscriptrsquo associates another JavaScript le with

12

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 13: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

the 3D object Upon activation of the 3D object the scripts are executed once inthe order of their inclusion Refer to the Acrobat 3D JavaScript Reference [3 ] forsyntax details The following 3D JavaScript loads an image le that was attached bylsquoaddresource=imagessunsetjpgrsquo and uses it as the scene background

sunset = new Image(new Resource(pdfimagessunsetjpg))reh = new RenderEventHandler()rehonEvent = function(event)

runtimeremoveEventHandler(this)eventcanvasbackgroundimage=sunset

runtimeaddEventHandler(reh)

For convenience subdirectory lsquojavascriptrsquo of the lsquomedia9rsquo installation contains three3D JavaScript les which may come in handy at times lsquoanimationjsrsquo enables embeddedkeyframe animation in 3D les lsquo3Dspintooljsrsquo enables the Spin tool of the 3D plugin foreasier rotating the 3D object with the mouse lsquoasylabelsjsrsquo adds lsquobillboard behaviourrsquoto text labels in Asymptote (ge v217) generated PRC les for improved visibility textlabels always face the camera while rotating the 3D object with the mouse

13

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 14: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 1 Entries in a VIEW section

key type remarksCOO three numbers centre of orbit see option lsquo3DcoorsquoC2C three numbers centre of orbit to camera vector see

option lsquo3Dc2crsquoROO number radius of orbit see option lsquo3DroorsquoC2W 12 numbers camera-to-world transformation

matrix see option lsquo3Dc2wrsquoAAC number camera aperture angle see option

lsquo3DaacrsquoORTHO number (optional) enables orthographic view see op-

tion lsquo3DorthorsquoPSOB string expert setting see option lsquo3DpsobrsquoROLL number camera roll see option lsquo3DrollrsquoBGCOLOR three numbers given as ltrgt ltggt ltbgt specify the

3D scene background colour (RGB)see option lsquo3Dbgrsquo

RENDERMODE string render mode of the 3D object seeoption lsquo3Drenderrsquo

LIGHTS string lighting scheme see optionlsquo3Dlightsrsquo

PARTSATTRS string allowed values are lsquokeeprsquo andlsquorestorersquo decides on whether to re-store or not original part attributesbefore applying new ones from thisview see option lsquo3Dpartsattrsrsquo

PART (sub-section) string part name as in the 3D ModelTree name argument is optionalif a UTF16NAME entry is present inthe sub-section opened by a PARTkeyword otherwise required seeTable 2 for list of possible entries

CROSSSECT (sub-section)

ndash see Table 3 for list of possible entries

14

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 15: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 2 Entries in a PART sub-section

key type remarksUTF16NAME hex string part name in UTF-16 (aka Unicode) en-

coded as a hexadecimal string optionalbut useful for part names composed of non-latin characters

VISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-ibility of this part

OPACITY number a number between 00 and 10 specifyingthe opacity of this part

RENDERMODE string rendermode of this part overrides globalRENDERMODE value in parent VIEW sectionsee option lsquo3Drenderrsquo

TRANSFORM 12 numbers transformation matrix dening the partrsquosposition and scaling

Table 3 Entries in a CROSSSECT sub-section

key type remarksCENTER three numbers central point coordinates of the cutting

planeNORMAL three numbers normal vector coordinates of the cutting

plane pointing into the cut-o regionOPACITY number a number between 00 and 10 specifying

the opacity of the cutting planeVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the vis-

ibility of the cutting planePLANECOLOR three numbers given as ltrgt ltggt ltbgt specify the colour

(RGB) of the cutting planeINTERSECTIONVISIBLE boolean a ag (lsquotruersquo or lsquofalsersquo) indicating the

visibility of the intersection of the cuttingplane with any 3D geometry

INTERSECTIONCOLOR three numbers given as ltrgt ltggt ltbgt specify the colour(RGB) for the cutting planersquos intersectionwith the 3D geometry

15

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 16: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

53 Control buttonsmediabutton[ltoptionsgt]ltnormal button text or graphicgt

This command inserts a clickable button for media control Actions to be performed arespecied through options lsquomediacommandrsquo lsquo3Dgotoviewrsquo and lsquojsactionrsquo By usingthese options repeatedly and in any combination several actions can be bound to onemedia button and one media button can be used to control several media at the sametime Media actions are started in the given order but performed in parallel becausethey do not wait for each other to nish The target of an action is specied via the labelthat was also given to a particular media by the lsquolabelrsquo option of lsquoincludemediarsquoIndividual button faces can be dened for the lsquomouse-overrsquo and lsquomouse-button-downrsquoevents using the lsquooverfacersquo and lsquodownfacersquo options Without options the buttonproduced does nothing The options provided are as follows

overface=ltmouse-over text or graphicgt

If specied the media button changes its appearance when the mouse pointer ismoved over it Without this option the button appearance does not change Anincludegraphics command may need to be enclosed in braces

downface=ltmouse-button-down text or graphicgt

If specied the media button changes its appearance when the mouse button is pressedwhile the pointer is over it An includegraphics command may need to be enclosedin braces

tooltip=lttip textgt

A box with lttip textgt is shown when the mouse pointer is moved over the button

3Dgotoview=ltlabel textgt[ltview specificationgt]

Selects a view from the list of predened views associated with a 3D media inclusion(see option lsquo3Dviewsrsquo) The target media is specied by ltlabel textgt as denedby the lsquolabelrsquo option of lsquoincludemediarsquo ltlabel textgt alone without a view spe-cication simply activates the 3D object if not yet activated ltview specificationgtwhich is separated from the label by a colon () can be one of the following an integerspecifying the zero-based index into the list of views in the 3D views le one oflsquoDrsquo lsquoFrsquo lsquoLrsquo lsquoNrsquo lsquoPrsquo indicating the default rst last next or previous view in the listof views a string delimited by lsquo(rsquo and lsquo)rsquo matching the name of a view as speciedby the lsquoVIEW=rsquo entry in the views le The option can be given several times tosimultaneously change the view in more than one 3D inclusion However it cannot beused to create an animation eect within the same 3D inclusion because 3Dgotoviewactions are executed in parallel

mediacommand=ltlabel textgt[ltcommandgt [(ltarg1gt) (ltarg2gt) ]]

A media command ltcommandgt with arguments if required is sent to a media inclusionidentied by ltlabel textgt as dened by the lsquolabelrsquo option of lsquoincludemediarsquoltlabel textgt alone without a command specication simply activates the media ifnot yet activated The option can be used multiple times within the same button totarget dierent media inclusions at the same time or to execute several commands forthe same media Depending on the type of the target media (3D or Flash) ltcommandgt iseither the name of a JavaScript function dened in a 3D JavaScript le associated with

16

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 17: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

the 3D media (see option lsquoadd3Djscriptrsquo) or the name of an ActionScript functionthat was exposed by the embedded Flash le ActionScript functions are exposedto the scripting context of the hosting document by using the ExternalInterfacecall within the Flash le Arguments to be passed to ltcommandgt must be enclosedin lsquo(rsquo and lsquo)rsquo and separated by spaces the whole list be nally enclosed in lsquo[rsquo andlsquo]rsquo even if there is only a single argument Arguments can be of Boolean type (truefalse) numbers (integer reals) and strings The number of arguments and their typesmust match the denition of the function to be called Media players VPlayerswf andAPlayerswf shipping with lsquomedia9rsquo expose a number of ActionScript functions thatcan be used with this option (see Tab 6 ) ltcommandgt [(ltarg1gt) (ltarg2gt) ]must be enclosed in braces if there are embedded equals signs or commas Examplesof using lsquomediacommandrsquo are given in Figs 2 and 6 c

jsaction=[ltlabel textgt]ltJavaScript codegt

The JavaScript code is executed in the context of the documentrsquos instance of the Ja-vaScript engine (there is one instance of the JavaScript engine per open documentin Adobe Reader) ltJavaScript codegt is required and must be enclosed in bracesUnlike media actions dened with options lsquomediacommandrsquo and lsquo3Dgotoviewrsquo the Ja-vaScript action dened here is not targeted at a particular embedded media and can beused to run arbitrary code Therefore ltlabel textgt is optional If provided it mustbe separated from ltJavaScript codegt by a colon However it is recommended toprovide a label text It ensures that annotRM[ltlabel textgt] is a valid JavaScriptreference to the AnnotRichMedia object annotRM[ltlabel textgt] can be usedto get access to the global context of the annotationrsquos instance of the 3D JavaScriptengine (there is one instance of the 3D JavaScript engine per activated RichMediaAnnotation with 3D content) The 3D JavaScript context of a 3D model can be accessedas annotRM[ltlabel textgt]context3D Refer to the Acrobat 3D JavaScript Ref-erence [3 ] for details on built-in JavaScript objects that are available in the 3D contextThe annotRM[ltlabel textgt]callAS() method may be used as an alternativeto the lsquomediacommandlsquo option Both serve as means of running ActionScript functionsexposed by embedded Flash les See [4 ] for details

draftfinal

See above

17

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 18: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

6 Embedding Flash video and soundimage slide-shows

A YouTube video clip as shown in Fig 1 may serve as a basic example of loadingFlash content from a URL to be displayed in an embedded fashion in a PDF documentIndeed a YouTube clip is nothing more than a small SWF le which loads a videostream and other necessary resources such as user controls and a player skin from aremote server It can be congured via ActionScript variables to play several videos ina row to play a video in a loop etc Player parameters are documented on httpcodegooglecomapisyoutubeplayer_parametershtml and can be passedto the player using either the lsquoflashvarsrsquo option as in the example or appended tothe URL string after the video ID A question mark lsquorsquo must be put between the videoID and the parameter string Some of the documented parameters such as lsquorelrsquo seemto have an eect only if they are passed as part of the URL

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

modestbranding=1 no YT logo in control barampautohide=1 controlbar autohideampshowinfo=0 no title and other info before startamprel=0 no related videos after end

]httpwwwyoutubecomvr382kfkqAF4rel=0

Figure 1 A YouTube video as an example of a Flash application loaded from a URL

Media les (video sound images) are always loaded and then played by a media playerapplication Four players are installed along with the lsquomedia9styrsquo package le threesimple players for video (lsquoVPlayerswfrsquo) sound (lsquoAPlayerswfrsquo) and slide-shows ofembedded andor remote (live or static) image les (lsquoSlideShowswfrsquo) and the fullyblown third-party media player lsquoStrobeMediaPlaybackswfrsquo with some xes to improveits usability The simple players are lsquochromelessrsquo that is they do not have graphicaluser controls Nevertheless interactivity is provided through left mouse button pressand release for playing pausing resuming playback through the playerrsquos context menu(right-click) and through the keyboard as summarized in Table 4 The player apps werecompiled using the open-source Apache Flex SDK [5 ] from XML source les whichreside in the doc folder of the package installation For lsquoStrobeMediaPlaybackswfrsquo

18

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton0)ocgs[i]state=false

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 19: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

only a patch le is included as the sources can be downloaded elsewhere

The improvements of lsquoStrobeMediaPlaybackswfrsquo in comparision to the original versionon SourceForgenet are

bull x video could not be restarted after end of playback if ActionScript variablelsquoautoRewindrsquo is set to lsquofalsersquo

bull new rst frame of video is shown as default poster instead of black stage

bull new playpause video by clicking on the stage (as with lsquoVPlayerswfrsquo) useful ina lecture situation

There is no need to copy the installed players into the directory of the document sourcefor embedding They will be found by LATEX without taking any further action

Like YouTube videos media players are congured via ActionScript variables which arepassed using option lsquoflashvarsrsquo Table 5 lists parameters available for lsquoVPlayerswfrsquolsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo Table 8 for lsquoStrobeMediaPlaybackswfrsquo

Playback of embedded video les is shown in Fig 2 Besides embedded les also videostreamed from remote servers via HTTP and RTMP protocols is supported as shownin Fig 5

Sound les and streams in the MP3 format can be played with lsquoAPlayerswfrsquo Fig 6

contains examples of an audio live stream and a remote MP3 sound le In one of thesound examples the player is loaded from a CTAN mirror during runtime because aninternet connection is required anyway for streaming the audio If a local sound le isto be embedded into the PDF this would have to be done in the same way as with thevideo le in one of the previous examples using the lsquoaddresourcersquo option

The slide-show application lsquoSlideShowswfrsquo requires a conguration le in the XMLle format It species the URLs from which the images will be loaded and may containoptional settings such as image captions refresh intervals for live images and initialrotation The syntax is documented in the conguration le template in Fig 3 The lename of a conguration le is passed to lsquoSlideShowswfrsquo using the lsquoxmlrsquo ActionScriptvariable Note that for security reasons the conguration le and lsquoSlideShowswfrsquo mustreside on the same server or be both embedded into the PDF Otherwise a securityerror will be thrown by the Flash Player plugin A slide-show example is shown inFig 4

lsquoVPlayerswfrsquo lsquoAPlayerswfrsquo and lsquoSlideShowswfrsquo expose a number of ActionScriptfunctions to the JavaScript engine of Adobe Reader allowing for playback control ofmedia through push buttons (see Sect 53 ) and various trigger events The functionsand their calling convention are listed in Tables 6 and 7 From within JavaScriptthese functions can be called using the lsquocallASrsquo (= call ActionScript) method of theAnnotRichMedia object As an example a call to the lsquoseekrsquo function looks like

annotRMmyvideocallAS(seek 123)

and a call to the parameter-less function lsquoplayPausersquo like

annotRMmyvideocallAS(playPause)

Both functions calls are sent to the media inclusion that was labelled lsquomyvideorsquo usingthe lsquolabelrsquo option of includemedia An example of playing and pausing a videoclip and setting the video source via interactive push buttons is given in Fig 2

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 20: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[label=some_dicewidth=06linewidthheight=045linewidthaddresource=randommp4 two video filesaddresource=cubemp4transparent transparent player backgroundactivate=pageopenpasscontext show VPlayers right-click menuflashvars=

source=randommp4amploop=true loop video

]VPlayerswf

mediabutton[mediacommand=some_diceplayPauseoverface=colorbluefboxstrut PlayPausedownface=colorredfboxstrut PlayPause

]fboxstrut PlayPausemediabutton[

mediacommand=some_dicesetSource [(randommp4)]]fboxstrut randommp4mediabutton[

mediacommand=some_dicesetSource [(cubemp4)]]fboxstrut cubemp4

Figure 2 Example of playing back two dierent embedded MP4 video les in the samevideo player instance The player lsquoVPlayerswfrsquo is also embedded in the PDF ExposedActionScript functions lsquoplayPausersquo and lsquosetSourcersquo of lsquoVPlayerswfrsquo (Table 6 ) areused to set-up media control buttons Dierent button faces have been dened for thePlayPause button Also playback can be contolled via the playerrsquos context (right-click)menu or the keyboard

20

media resource
media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton1)ocgs[i]state=false

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 21: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

ltxml version=10gtltSlideShowgt

lt--Configuration file template for SlideShowswf

SlideShowswf can display life and static PNGJPEGGIF image files fromremote servers or residing on the same server as the app itself

Pass this file to SlideShowswf using the `xml=ltconfiguration filegtFlashVar

NOTE For security reasons of Flash Player the configuration file andSlideShowswf must reside on the same web server or be both embedded intothe PDF Different web servers or the combination of web server locationand embedding into the PDF throws a security error

An image definition starts with ltImg [attributes]gt and ends with ltImggtAll attributes in the opening ltImg [attributes]gt tag are optional

live=ltrefresh interval in [s]gt for live remote imagerot90=ltinteger numbergt initial rotation by number90deg

Inside an image definition at least one ltURL [attributes]gtltURLgtelement is required The attributes are optional More than one URL may begiven to provide image files at various resolutions The best one fittingwithin the current display size will be chosen dynamically In the case ofmultiple URLs the actual resolution of each image should be told using the

size=ltwidthgtxltheightgt

attribute which specifies the image file dimensions in pixels

Some servers generate bitmap graphics at arbitrary resolution upon requestIn such cases one or both of the attributes

width=ltwidth patterngt height=ltheight patterngt

may be given in the opening URL tag ltwidth patterngt and ltheight patterngtif present in the URL string will be substituted with the current displaydimensions

An image URL given between ltURLgt and ltURLgt can be absolute that isstarting with http or relative to the location of SlideShowswf

The ltcaptiongtltcaptiongt element inside the image definition is optional--gtltImg live=3gt lt-- Live image refreshed every 3 seconds --gt

ltcaptiongtMow-the-lawn simulation (live remote image)ltcaptiongtltURLgthttp1618034comcorner-iconpngltURLgt

ltImggtltImggt lt-- remote image with dynamic size URL --gt

ltcaptiongtAn algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the displayltcaptiongt

ltURL width=gthttpsopenclipartorgimagepxsvg_to_png1374071304882618pngltURLgtltImggtltImggt lt-- remote image with multiple URLs of different resolution --gt

ltcaptiongtCTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image)ltcaptiongt

ltURL size=200x178 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200pngltURLgt

ltURL size=400x355 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400pngltURLgt

ltURL size=800x710 gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800pngltURLgt

ltURL size=1200x1065gthttpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200pngltURLgt

ltImggtltImg rot90=3gt lt-- static image with URL relative to SlideShowswf location --gt

ltcaptiongtStatic embedded image file with initial rotation of 3x90degPress r or R to change orientationltcaptiongt

ltURLgtfilescubeposterpngltURLgtltImggt

ltSlideShowgt

Figure 3 Conguration le template (XML format) for lsquoSlideShowswfrsquo

21

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 22: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[width=linewidthheight=linewidthactivate=pageopenaddresource=filesconfigxml embedded configurationaddresource=filescubeposterpng embedded image fileflashvars=xml=filesconfigxmlpasscontext show the players context menu

]SlideShowswf

Figure 4 Slide-show example with one embedded and several remote image les one ofwhich is a live image Images 2 and 3 are examples of remote images with variable res-olution the best tting image resolution is requested from the server depending on thecurrent display size The listing in Fig 3 is used as content of le lsquocongxmlrsquo Manuallycycle forwards through the images by mouse-click or backwards by +mouse-clickPlaypause auto-cycling through the slide-show by hitting Space Also the context(right-click) menu of the player can be used

22

media resource

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

media resource
media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton2)ocgs[i]state=false

Mow-the-lawn simulation (live remote image) http1618034comcorner-iconpng An algorithm must be seen to be believed (Donald E Knuth)Remote image URL with dynamic size that is reloaded while resizing the display httpsopenclipartorgimagepxsvg_to_png1374071304882618png CTAN lion drawing by Duane Bibby Thanks to wwwctanorgRemote image with URLs at various resolutions (responsive image) httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_200png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_400png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_800png httpmirrorsibiblioorgCTANmacroslatexcontribmedia9docfilesctan_lion_1200png Static embedded image file with initial rotation of 3x90degPress r or R to change orientation filescubeposterpng

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 23: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 4 Keyboard control of media players (a) lsquoVPlayerswfrsquo amp lsquoAPlayerswfrsquo (b)lsquoSlideShowswfrsquo Players must have the focus to take eect Click onto the players ifnecessary

(a)keys action

Space playpauseHome End go to startend

seek backwardsforwards decreaseincrease speaker volume

m muteunmutectrl + ctrl + ctrl + (APlayerswf only) change sound speaker

balance

(b)keys action

Space playpause auto-cycling through slides previousnext slide

Home End go to rstlast slider R rightleft rotate current slide by 90deg

includemedia[width=06linewidthheight=03375linewidth 169activate=pageopenflashvars=

src=rtmpstreamingmusicindianaedu1935onDemandmp4media20090327_VarRussianTheme-h264-480m4v

ampscaleMode=stretch

]StrobeMediaPlaybackswf

Figure 5 Example of video streamed from an RTMP server This example uses mediaplayer lsquoStrobeMediaPlayBackswfrsquo physically embedded in the PDF

23

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton3)ocgs[i]state=false

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 24: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 5 Parameters (ActionScript variables) for media players (a) lsquoVPlayerswfrsquo amplsquoAPlayerswfrsquo (b) lsquoSlideShowswfrsquo shipping with media9 Parameters are passed as alsquoamprsquo-separated string using lsquoflashvarsrsquo option

(a)parameter descriptionsource=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)to online media le

autoPlay=true|false if =true automatically starts playbackafter activation (see option lsquoactivation)rsquo

autoRewind=true|false (VPlayerswf only) if =true automaticallyrewind to the rst frame after playback hasnished default is lsquofalsersquo

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

hideBar=true|false (APlayerswf only) if =true the progressbar indicating the play position is notshown

volume=ltvalue between 00and 10gt

sets volume of the sound

balance=ltvalue between-10 and 10gt

(APlayerswf only) sets balance of soundspeakers

(b)parameter descriptionxml=ltfile path or URLgt (required) path to embedded (option

lsquoaddresourcersquo) or URL of remote cong-uration le

delay=ltnumbergt sets time delay in seconds for transitionbetween slides during playback default 5 s

autoPlay=true|false if =true automatically starts cyclingthrough slides after activation (see optionlsquoactivation)rsquo

24

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 25: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 6 Exposed ActionScript functions of media players lsquoVPlayerswfrsquo andlsquoAPlayerswfrsquo that can be called from within media buttons (see Sect 53 ) or fromJavaScript using the lsquocallASrsquo method of the lsquoAnnotRichMediarsquo JavaScript object(see [4 ] for further information)

function argument descriptionplay number (optional) play media optionally starting at number

seconds oset into the media lepause number (optional) pause media optionally at the given oset

of number seconds into the media leplayPause toggle between play and pausesetSource string load another media le (path to le embed-

ded using option lsquoaddresourcersquo or URL)seek number move the play location to a time oset from

the beginning of the media argument meas-ured in seconds

rewind rewind media to the beginning (withoutpausing it)

volume number between 0and 1

set volume level

balance number between minus1and +1

(APlayerswf only) set speaker balance

mute mute or unmute (toggle) the audio of themedia

currentTime returns current playhead position inseconds only useful in JavaScript vialsquocallASrsquo method

duration returns duration of the media videosoundle currently loaded only useful in Java-Script via lsquocallASrsquo method

playing returns boolean value lsquotruersquo if the mediais currently playing lsquotruersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

muted returns boolean value lsquotruersquo if the soundis currently muted lsquofalsersquo otherwise onlyuseful in JavaScript via lsquocallASrsquo method

25

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 26: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show APlayers right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayerswf

(a) Singing bird

includemedia[flashvars=

source=httpmp3livetv-radiocomfrancecultureallfranceculturehautdebitmp3

ampautoPlay=truetransparentpasscontext show APlayers right-click menu

]colorbluefboxListen live to Radio France CulturehttpmirrorsibiblioorgpubmirrorsCTANmacroslatexcontribmedia9playersAPlayerswf

(b) Listen live to Radio France Culture

includemedia[label=song49flashvars=source=httpwwwopenbsdorgsongssong49mp3transparentpasscontext show VPlayers right-click menu

]colorbluefboxListen to OpenBSD 49 release songAPlayerswfmediabutton[

mediacommand=song49play[(55)]mediacommand=song49pause[(37)]

]fboxFirst versemediabutton[

mediacommand=song49play[(39)]mediacommand=song49pause[(49)]

]fboxThe Answermediabutton[

mediacommand=song49play[(2065)]mediacommand=song49pause[(221)]

]fboxHarmonica solo

Listen to OpenBSD 49 release song(c)

Figure 6 Example of (a) embedded sound le (b) streamed audio and (c) progressivelydownloaded MP3 ID3 tags lsquotitlersquo lsquoartistrsquo and lsquoalbumrsquo are displayed if contained in theMP3 stream or le In (b) the sound player APlayerswf is loaded from a CTAN mirrorupon activation

26

media resource

Birdsong mild sunny day

Stephan

3654539

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton4)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton5)ocgs[i]state=false

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton6)ocgs[i]state=false

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 27: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[activate=onclick defaultaddresource=cubemp4flashvars=

source=cubemp4ampautoPlay=true start playing on activationamploop=true

passcontext show players right-click menu

]includegraphics[height=045linewidth]cubeposterVPlayer9swf

includemedia[addresource=birdmp3flashvars=

source=birdmp3ampautoPlay=true

transparentpasscontext show players right-click menu

]colorblueframebox[04linewidth][c]Singing birdAPlayer9swf

Singing bird

Figure 7 Video and sound examples that should run in Adobe Reader for Linux upto version 941 Here players lsquoVPlayer9swfrsquo and lsquoAPlayer9swfrsquo are used Both arecompatible with Adobe Flash Player 9 plugin that is bundled with the Reader Also thevideo player needs to be activated by mouse click (which is the default) We provide aposter image that is shown in the inactive state

27

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton7)ocgs[i]state=false

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton8)ocgs[i]state=false

Birdsong mild sunny day

Stephan

3654539

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 28: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 7 Exposed ActionScript functions of slide-show player lsquoSlideShowswfrsquo that canbe called from within media buttons or from JavaScript

function argument descriptionplay play slide-showpause pause slide-showplayPause toggle between play and pausesetXML string load another conguration le (path

to le embedded using optionlsquoaddresourcersquo or URL)

seek int number go to slide lsquonumberrsquo (zero-based)slideNum returns current slide number (zero-

based) only useful in JavaScript vialsquocallASrsquo method

numSlides returns total number of slides in theslide-show only useful in JavaScript vialsquocallASrsquo method

playing returns boolean value lsquotruersquo if the slide-show is currently playing lsquotruersquo oth-erwise only useful in JavaScript vialsquocallASrsquo method

rotate int number (op-tional)

rotate current slide by numbertimes90deg

28

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 29: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

Table 8 Parameters (ActionScript variables) for lsquoStrobeMediaPlaybackswfrsquo shippingwith media9 Parameters are passed as a lsquoamprsquo-separated string using lsquoflashvarsrsquo option

parameter descriptionsrc=ltfile path or URLgt (required) path to embedded media le (see

option lsquoaddresourcersquo) or URL (http rtmp)of online media le

autoPlay=true|false default false if =true automaticallystarts playback after activation (see optionlsquoactivation)rsquo

autoRewind=true|false default true if =false keep last frameafter end of playback

loop=true|false if =true media is played in a loopscaleMode=letterbox|none|

stretch|zoomdefault letterbox determines how toscale the video in order to t into player

controlBarMode=docked|floating|none

default docked determines position andvisibility of control bar

controlBarAutoHide=true|false

default true automatically hide or notcontrol bar

controlBarAutoHideTimeout=ltnumber [s]gt

default 3 time span before auto-hide

volume=ltvalue between 00and 10gt

sets volume of the sound

audioPan=ltvalue between-10 and 10gt

default 0 sets balance of sound speakers

muted=true|false default false mute or not sound

29

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 30: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

7 Embedding 3D objects

71 IntroductionAdobe AcrobatReader 7 was the rst version to allow for embedding 3-dimensionalgraphic objects such as CAD models or 3D scientic data that can be manipulatedinteractively by the user U3D was the rst supported format and was mainly developedby Right Hemisphere and Adobe U3D had some deciencies and was later replacedby the PRC format after Adobe purchased the original developer the French companylsquoTrade and Technology Francersquo U3D is still supported but PRC is preferred as it allowsfor exact representation of curved surfaces and better compression Both U3D andPRC specications are public [6 7 ]

Currently two open-source software packages are known to export into the PRC leformat The rst one is Asymptote [8 ] which is a descriptive 2D and 3D vector graphicslanguage and interpreter and which uses TEX to typeset labels and equations It allowsfor high quality mathematical gures and technical drawings An impressive galleryof examples can be found on its Web site The second one is MathGL [9 ] a library forscientic data visualization It provides interfaces to a number of programming andscripting languages as well as an interpreter for its own command language lsquoMGLrsquo

MeshLab [11 ] is an open-source conversion and processing software for 3D mesh datawhich can import from and export to a number of le formats Its U3D export lter isbased on the open-source lsquoUniversal 3D Sample Softwarersquo [10 ]

There are a few options to includemedia which dene how the 3D object is posi-tioned within the view port of a virtual camera or conversely how the virtual camerais positioned and oriented within a coordinate system called lsquoThe Worldrsquo which bearsthe 3D object at a xed position Fig 8 should help to grasp the scenery The virtualcamera is orbiting at a distance of ROO (option lsquo3Droorsquo) around the centre of orbitspecied by the position vector minusminusminusrarrCOO (option lsquo3Dcoorsquo) ^AAC (option lsquo3Daacrsquo) is thecamerarsquos aperture angle The direction vector minusminusminusrarrC2C (option lsquo3Dc2crsquo) is needed to spe-cify the initial camera position The camera may be given an initial roll angle (optionlsquo3Drollrsquo) around its optical axis (minus1) middot minusminusminusrarrC2C Fig 8 shows the camera parameters forthe perspective view mode Alternatively the orthographic view mode may be chosenIn orthographic view the 3D object is parallelly projected onto the virtual camera chipBefore reaching the camera chip the projected image must be scaled in order to tonto the chip Orthographic view can be enabled using the lsquo3Dorthorsquo option whichtakes the scaling factor as its argument

Above options dene the default view i e the view that is shown initially after activ-ating the 3D object in the Reader Of course once activated the camera position canbe changed using the mouse and one can change forth and back between perspectiveand orthographic viewing modes using the 3D tool bar

By default the virtual camera sits at the origin (0 0 0) of the World looking in the pos-itive Y direction i e default settings of 3Droo=0 3Dcoo=0 0 0 and 3Dc2c=0 -1 0are assumed (Note that minusminusminusrarrC2C is the opposite of the optical axis vector) Thus in orderto get a lsquofront viewrsquo of the 3D object it is sucient to set the radius of orbit i e thedistance between camera and object appropriately Sometimes you may want to adjustthe orbital centre i e the target of the camera as well in particular if the object isirregularly shaped or if it is not centred around the World origin Fortunately it is

30

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 31: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

minusminusminusrarrC2C Y

X

Z

minusminusminusrarrCOO

(0 0 0)

^AAC

ROO

Figure 8 Camera and 3D object in the World System XYZ centre of orbit positionvector minusminusminusrarrCOO centre of orbit to camera direction vector minusminusminusrarrC2C radius of orbit ROO aperture angle of camera ^AAC

possible to let the values of the corresponding options be determined automaticallyChoosing option lsquo3Dmenursquo adds lsquoGenerate Default Viewrsquo to the context menu of theactivated 3D scene Selecting this entry calculates and outputs optimal camera settingswhich can be inserted into the option list of includemedia

Additional resource les that are needed to render the 3D scene can be embedded usingthe lsquoaddresourcersquo option Typical resources are bitmaps and Flash les (even animatedand interactive ones) to be used as materials or scene backgrounds as well as additional3D objects in the U3D or PRC le format The allowed le formats of bitmapped imageles depend on the LATEXworkow LATEXrarr dvipsrarr ps2pdfDistiller accepts PS andEPS les pdfLATEX accepts PNG JPEG and JBIG2 (X E)LATEXrarr (x)dvipdfmx acceptsPNG and JPEG 3D JavaScript is necessary to load these resources upon activation 3DJavaScript les are attached using the lsquoadd3Djscriptrsquo option

Below several examples of embedded 3D les are shown The rst one Fig 9 is aPRC le generated with Asymptote Note the text labels always facing the camerathanks to the attached 3D JavaScript le lsquoasylabelsjsrsquo The second example Fig 10

31

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 32: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

demonstrates the use of a views le which denes additional named views of the 3Dobject Moreover the possibilities of the extended 3D context menu can be evaluatedThey were enabled by adding the lsquo3Dmenursquo option to includemedia All part andscene rendering attributes that can be changed via the lsquoPart Optionsrsquo and lsquoViewingOptionsrsquo menu entries as well as a cross section to be added with the lsquoCross Sectionrsquomenu entry can be saved into a new view (lsquoGet Current Viewrsquo) Position orientationand scaling of individual parts and of the cross section can be changed using thekeyboard (keys X + X Y + Y Z + Z S

+ S ) The third example Fig 11 shows an animated 3D object The animationitself and the functions called by pressing the controls are dened in a 3D JavaScriptle attached to the model

includemedia[width=08linewidthheight=08linewidthadd3Djscript=asylabelsjs upright text labelsadd3Djscript=3Dspintooljs let scene rotate about z-axis 3Dcoo 3Droo values found with `Generate Default View from context menu3Dmenu3Dc2c=4 2 33Dcoo=4413303375244141 2195653200149536 -00000114440917968753Droo=42949035778293376

]includegraphicsepixposterepixprc

Figure 9 Embedded PRC le produced with Asymptote making use of convenience3D JavaScripts lsquoasylabelsjsrsquo and lsquo3Dspintooljsrsquo mentioned above

32

media resource

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

media resource

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

media resource

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton9)ocgs[i]state=false

(C) 2012 Michail Vidiassov John C Bowman Alexander Grahn asylabelsjs version 20120912 3D JavaScript to be used with media9sty (option `add3Djscript) for Asymptote generated PRC files adds billboard behaviour to text labels in Asymptote PRC files so that they always face the camera under 3D rotation This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahnvar bbnodes=new Array() billboard meshesvar bbtrans=new Array() billboard transformsfunction fulltransform(mesh) var t=new Matrix4x4(meshtransform) if(meshparentname = ) var parentTransform=fulltransform(meshparent) tmultiplyInPlace(parentTransform) return t else return t find all text labels in the scene and determine pivoting pointsvar nodes=scenenodesvar nodescount=nodescountvar third=1030for(var i=0 i lt nodescount i++) var node=nodesgetByIndex(i) var name=nodename var end=namelastIndexOf()-1 if(end gt 0) if(namecharAt(end) == 001) var start=namelastIndexOf(-)+1 if(end gt start) nodename=namesubstr(0start-1) var nodeMatrix=fulltransform(nodeparent) var c=nodeMatrixtranslation position var d=Mathpow(Mathabs(nodeMatrixdeterminant)third) scale bbnodespush(node) bbtranspush(Matrix4x4()scale(ddd)translate(c)multiply(nodeMatrixinverse)) var camera=scenecamerasgetByIndex(0) var zero=new Vector3(000)var bbcount=bbnodeslength event handler to maintain camera-facing text labelsbillboardHandler=new RenderEventHandler()billboardHandleronEvent=function(event) var T=new Matrix4x4() TsetView(zerocamerapositionsubtract(cameratargetPosition) cameraupsubtract(cameraposition)) for(var j=0 j lt bbcount j++) bbnodes[j]transformset(Tmultiply(bbtrans[j])) runtimerefresh() runtimeaddEventHandler(billboardHandler)runtimerefresh()

(C) 2012 Alexander Grahn 3Dspintooljs version 20120301 3D JavaScript to be used with media9sty (option `add3Djscript) enables the Spin tool (also accessible via 3D toolbar or context menu) upon activation of the 3D scene the scene then rotates around the upright axis while dragging with the mouse This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A GrahnruntimesetCurrentTool(runtimeTOOL_NAME_SPIN)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 33: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[label=dicewidth=05linewidthheight=05linewidthactivate=pageopen3Dtoolbar 3Dmenu3Dviews=dicevws

]diceu3d

mediabutton[3Dgotoview=diceN]fboxNext viewmediabutton[3Dgotoview=dice(Back)]fboxView `Backmediabutton[3Dgotoview=dice5]fbox6th view in the list

Contents of lsquodicevwsrsquoVIEW=Front

ROO=27ENDVIEW=Back

ROO=27C2C=0 1 0

ENDVIEW=Left

ROO=27C2C=-1 0 0

ENDVIEW=Right

ROO=27C2C=1 0 0

ENDVIEW=Top

ROO=27C2C=0 0 1

ENDVIEW=Bottom

ROO=27C2C=0 0 -1

ENDVIEW=Fish Eye at Centre

AAC=130END

Figure 10 Embedded U3D le based on a VRML model by Peter Whitehousehttpwwwwonkoinfovrmlindexhtm conversion to U3D was done usingDeepExplorationreg[12 ] The le lsquodicevwsrsquo provides predened views Buttons arecreated with mediabutton using the lsquo3Dgotoviewrsquo option

33

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton10)ocgs[i]state=false

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 34: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

includemedia[label=maltewidth=05linewidthheight=05linewidthactivate=pageopen3Dmenu3Dc2c=1 1 13Dcoo=-0001042630523443222 14577869224116568e-19 00282350014895200733Droo=02604540212188131add3Djscript=maltejs

]malteu3d

mediabutton[jsaction=malteannotRM[malte]context3DcntrClockWise()

]includegraphics[height=144em]boutonamediabutton[

jsaction=malteannotRM[malte]context3Dpause()]includegraphics[height=144em]boutonbmediabutton[

jsaction=malteannotRM[malte]context3DclockWise()]includegraphics[height=144em]boutonchspace1emmediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(111)]includegraphics[height=144em]boutondmediabutton[

jsaction=malteannotRM[malte]context3DorigSpeed()]includegraphics[height=144em]boutonemediabutton[

jsaction=malteannotRM[malte]context3DscaleSpeed(11)]includegraphics[height=144em]boutonf

Figure 11 Animated U3D example of a Maltese drive contributed by Jean-Luc ChesnotThe animation and the functions called in the JavaScript actions of the media buttonsare dened in the JavaScript le lsquomaltejsrsquo

34

media resource

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

media resource

var ocgs=hostgetOCGs(hostpageNum)for(var i=0iltocgslengthi++)if(ocgs[i]name==MediaPlayButton11)ocgs[i]state=false

crank=thisscenenodesgetByName(manivelle-1-1)cross=thisscenenodesgetByName(croix-1-1)function cntrClockWise()dir=1 speed=lastspeedfunction pause()if(speed)lastspeed=speed speed=0function clockWise()dir=-1 speed=lastspeedfunction scaleSpeed(s)lastspeed=s if(speed) speed=lastspeedfunction origSpeed()lastspeed=1 if(speed) speed=lastspeedOcrank=new Vector3(-0025 0 0)Ocross=new Vector3(0025 0 0)axeZ=new Vector3(001)mx4x4=new Matrix4x4()var omega0=MathPI init angular frequency (half turn per second)var dir=1 init directionvar speed=0 speed multipliervar lastspeed=1var alpha=0timeEvHnd=new TimeEventHandler()timeEvHndonEvent=function(event) var dalpha=dirspeedomega0eventdeltaTime if (dalpha=0) mx4x4setIdentity() mx4x4rotateAboutLineInPlace(alphaOcrankaxeZ) cranktransformset(mx4x4) with (Math) if (alphalt3PI2) beta=0 else beta=-atan(sin(alpha+PI4)(sqrt(2)-cos(alpha+PI4)))+PI4 mx4x4setIdentity() mx4x4rotateAboutLineInPlace(betaOcrossaxeZ) crosstransformset(mx4x4) alpha+=dalpha+2MathPI alpha=2MathPI sceneupdate() runtimeaddEventHandler(timeEvHnd)

(C) 2012--today Alexander Grahn 3Dmenujs version 20140923 3D JavaScript used by media9sty Extended functionality of the (right click) context menu of 3D annotations 1) Adds the following items to the 3D context menu `Generate Default View Finds good default camera settings returned as options for use with the includemedia command `Get Current View Determines camera cross section and part settings of the current view returned as `VIEW section that can be copied into a views file of additional views The views file is inserted using the `3Dviews option of includemedia `Cross Section Toggle switch to add or remove a cross section into or from the current view The cross section can be moved in the x y z directions using x y z and X Y Z keys on the keyboard be tilted against and spun around the upright Z axis using the UpDown and LeftRight arrow keys and caled using the s and S keys 2) Enables manipulation of position and orientation of indiviual parts and groups of parts in the 3D scene Parts which have been selected with the mouse can be scaled moved around and rotated like the cross section as described above To spin the parts around their local up-axis keep Control key pressed while using the UpDown and LeftRight arrow keys This work may be distributed andor modified under the conditions of the LaTeX Project Public License The latest version of this license is in httpmirrorsctanorgmacroslatexbaselppltxt This work has the LPPL maintenance status `maintained The Current Maintainer of this work is A Grahn The code borrows heavily from Bernd Gaertners `Miniball software originally written in C++ for computing the smallest enclosing ball of a set of points see httpwwwinfethzchpersonalgaertnerminiballhtmlhostconsoleshow()constructor for doubly linked listfunction List() thisfirst_node=null thislast_node=new Node(undefined)Listprototypepush_back=function(x) var new_node=new Node(x) if(thisfirst_node==null) thisfirst_node=new_node new_nodeprev=null else new_nodeprev=thislast_nodeprev new_nodeprevnext=new_node new_nodenext=thislast_node thislast_nodeprev=new_nodeListprototypemove_to_front=function(it) var node=itget() if(nodenext=null ampamp nodeprev=null) nodenextprev=nodeprev nodeprevnext=nodenext nodeprev=null nodenext=thisfirst_node thisfirst_nodeprev=node thisfirst_node=node Listprototypebegin=function() var i=new Iterator() itarget=thisfirst_node return(i)Listprototypeend=function() var i=new Iterator() itarget=thislast_node return(i)function Iterator(it) if( it=undefined ) thistarget=ittarget else thistarget=null Iteratorprototypeset=function(it)thistarget=ittargetIteratorprototypeget=function()return(thistarget)Iteratorprototypederef=function()return(thistargetdata)Iteratorprototypeincr=function() if(thistargetnext=null) thistarget=thistargetnextconstructor for node objects that populate the linked listfunction Node(x) thisprev=null thisnext=null thisdata=xfunction sqr(r)return(rr)helper functionMiniball algorithm by B Gaertnerfunction Basis() thism=0 thisq0=new Array(3) thisz=new Array(4) thisf=new Array(4) thisv=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisa=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thisc=new Array(new Array(3) new Array(3) new Array(3) new Array(3)) thissqr_r=new Array(4) thiscurrent_c=thisc[0] thiscurrent_sqr_r=0 thisreset()Basisprototypecenter=function()return(thiscurrent_c)Basisprototypesize=function()return(thism)Basisprototypepop=function()--thismBasisprototypeexcess=function(p) var e=-thiscurrent_sqr_r for(var k=0klt3++k) e+=sqr(p[k]-thiscurrent_c[k]) return(e)Basisprototypereset=function() thism=0 for(var j=0jlt3++j) thisc[0][j]=0 thiscurrent_c=thisc[0] thiscurrent_sqr_r=-1Basisprototypepush=function(p) var i j var eps=1e-32 if(thism==0) for(i=0ilt3++i) thisq0[i]=p[i] for(i=0ilt3++i) thisc[0][i]=thisq0[i] thissqr_r[0]=0 else for(i=0ilt3++i) thisv[thism][i]=p[i]-thisq0[i] for(i=1iltthism++i) thisa[thism][i]=0 for(j=0jlt3++j) thisa[thism][i]+=thisv[i][j]thisv[thism][j] thisa[thism][i]=(2thisz[i]) for(i=1iltthism++i) for(j=0jlt3++j) thisv[thism][j]-=thisa[thism][i]thisv[i][j] thisz[thism]=0 for(j=0jlt3++j) thisz[thism]+=sqr(thisv[thism][j]) thisz[thism]=2 if(thisz[thism]ltepsthiscurrent_sqr_r) return(false) var e=-thissqr_r[thism-1] for(i=0ilt3++i) e+=sqr(p[i]-thisc[thism-1][i]) thisf[thism]=ethisz[thism] for(i=0ilt3++i) thisc[thism][i]=thisc[thism-1][i]+thisf[thism]thisv[thism][i] thissqr_r[thism]=thissqr_r[thism-1]+ethisf[thism]2 thiscurrent_c=thisc[thism] thiscurrent_sqr_r=thissqr_r[thism] ++thism return(true)function Miniball() thisL=new List() thisB=new Basis() thissupport_end=new Iterator()Miniballprototypemtf_mb=function(it) var i=new Iterator(it) thissupport_endset(thisLbegin()) if((thisBsize())==4) return for(var k=new Iterator(thisLbegin())kget()=iget()) var j=new Iterator(k) kincr() if(thisBexcess(jderef()) gt 0) if(thisBpush(jderef())) thismtf_mb(j) thisBpop() if(thissupport_endget()==jget()) thissupport_endincr() thisLmove_to_front(j) Miniballprototypecheck_in=function(b) thisLpush_back(b)Miniballprototypebuild=function() thisBreset() thissupport_endset(thisLbegin()) thismtf_mb(thisLend())Miniballprototypecenter=function() return(thisBcenter())Miniballprototyperadius=function() return(Mathsqrt(thisBcurrent_sqr_r))functions called by menu itemsfunction calc3Dopts () create Miniball object var mb=new Miniball() auxiliary vector var corner=new Vector3() iterate over all visible mesh nodes in the scene for(i=0iltscenemeshescounti++) var mesh=scenemeshesgetByIndex(i) if(meshvisible) continue local to parent transformation matrix var trans=meshtransform build local to world transformation matrix by recursively multiplying the parents transf matrix on the right var parent=meshparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent get the bbox of the mesh (local coordinates) var bbox=meshcomputeBoundingBox() transform the local bounding box corner coordinates to world coordinates for bounding sphere determination BBoxmin cornerset(bboxmin) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) BBoxmax cornerset(bboxmax) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) remaining six BBox corners cornerset(bboxminx bboxmaxy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxminx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxminy bboxmaxz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) cornerset(bboxmaxx bboxmaxy bboxminz) cornerset(transtransformPosition(corner)) mbcheck_in(new Array(cornerx cornery cornerz)) compute the smallest enclosing bounding sphere mbbuild() current camera settings var camera=scenecamerasgetByIndex(0) var res= initialize result string aperture angle of the virtual camera (perspective projection) or orthographic scale (orthographic projection) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf(n3Daac=s aac) else cameraviewPlaneSize=2mbradius() res+=hostutilprintf(n3Dortho=s 1cameraviewPlaneSize) camera roll var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf(n3Droll=sroll) target to camera vector var c2c=new Vector3() c2cset(cameraposition) c2csubtractInPlace(cameratargetPosition) c2cnormalize() if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf(n3Dc2c=s s s c2cx c2cy c2cz) new camera settings bounding sphere centre --gt new camera target var coo=new Vector3() cooset((mbcenter())[0] (mbcenter())[1] (mbcenter())[2]) if(coolength) res+=hostutilprintf(n3Dcoo=s s s coox cooy cooz) radius of orbit if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var roo=mbradius() Mathsin(aac MathPI 360) else orthographic projection var roo=mbradius() res+=hostutilprintf(n3Droo=s roo) update camera settings in the viewer var currol=cameraroll cameratargetPositionset(coo) camerapositionset(cooadd(c2cscale(roo))) cameraroll=currol determine background colour rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf(n3Dbg=s s s rgbr rgbg rgbb) determine lighting scheme switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+=hostutilprintf(n3Dlights=s curlights) determine global render mode switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak if(currender=Solid) res+=hostutilprintf(n3Drender=s currender) write result string to the console hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Copy and paste the following text to then+ option list of includemedian + res + n)function get3Dview () var camera=scenecamerasgetByIndex(0) var coo=cameratargetPosition var c2c=camerapositionsubtract(coo) var roo=c2clength c2cnormalize() var res=VIEW=insert optional name heren if((coox==0 ampamp cooy==0 ampamp cooz==0)) res+=hostutilprintf( COO=s s sn coox cooy cooz) if((c2cx==0 ampamp c2cy==-1 ampamp c2cz==0)) res+=hostutilprintf( C2C=s s sn c2cx c2cy c2cz) if(roo gt 1e-9) res+=hostutilprintf( ROO=sn roo) var roll = cameraroll180MathPI if(hostutilprintf(4f roll)=0) res+=hostutilprintf( ROLL=sn roll) if(cameraprojectionType==cameraTYPE_PERSPECTIVE) var aac=camerafov 180MathPI if(hostutilprintf(4f aac)=30) res+=hostutilprintf( AAC=sn aac) else if(hostutilprintf(4f cameraviewPlaneSize)=1) res+=hostutilprintf( ORTHO=sn 1cameraviewPlaneSize) rgb=scenebackgroundgetColor() if((rgbr==1 ampamp rgbg==1 ampamp rgbb==1)) res+=hostutilprintf( BGCOLOR=s s sn rgbr rgbg rgbb) switch(scenelightScheme) case sceneLIGHT_MODE_FILE curlights=Artworkbreak case sceneLIGHT_MODE_NONE curlights=Nonebreak case sceneLIGHT_MODE_WHITE curlights=Whitebreak case sceneLIGHT_MODE_DAY curlights=Daybreak case sceneLIGHT_MODE_NIGHT curlights=Nightbreak case sceneLIGHT_MODE_BRIGHT curlights=Hardbreak case sceneLIGHT_MODE_RGB curlights=Primarybreak case sceneLIGHT_MODE_BLUE curlights=Bluebreak case sceneLIGHT_MODE_RED curlights=Redbreak case sceneLIGHT_MODE_CUBE curlights=Cubebreak case sceneLIGHT_MODE_CAD curlights=CADbreak case sceneLIGHT_MODE_HEADLAMP curlights=Headlampbreak if(curlights=Artwork) res+= LIGHTS=+curlights+n switch(scenerenderMode) case sceneRENDER_MODE_BOUNDING_BOX defaultrender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX defaultrender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE defaultrender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES defaultrender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES defaultrender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME defaultrender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME defaultrender=ShadedWireframebreak case sceneRENDER_MODE_SOLID defaultrender=Solidbreak case sceneRENDER_MODE_TRANSPARENT defaultrender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME defaultrender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME defaultrender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION defaultrender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE defaultrender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION defaultrender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME defaultrender=HiddenWireframebreak if(defaultrender=Solid) res+= RENDERMODE=+defaultrender+n detect existing Clipping Plane (3D Cross Section) var clip=null if( clip=scenenodesgetByName($$$$$$)|| clip=scenenodesgetByName(Clipping Plane) ) for(var i=0iltscenenodescounti++) var nd=scenenodesgetByIndex(i) if(nd==clip||ndname==) continue var ndUTFName= for (var j=0 jltndnamelength j++) var theUnicode = ndnamecharCodeAt(j)toString(16) while (theUnicodelengthlt4) theUnicode = 0 + theUnicode ndUTFName += theUnicode var end=ndnamelastIndexOf() if(endgt0) var ndUserName=ndnamesubstr(0end) else var ndUserName=ndname respart= PART=+ndUserName+n respart+= UTF16NAME=+ndUTFName+n defaultvals=true if(ndvisible) respart+= VISIBLE=falsen defaultvals=false if(ndopacitylt10) respart+= OPACITY=+ndopacity+n defaultvals=false if(ndconstructorname==Mesh) currender=defaultrender switch(ndrenderMode) case sceneRENDER_MODE_BOUNDING_BOX currender=BoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX currender=TransparentBoundingBoxbreak case sceneRENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE currender=TransparentBoundingBoxOutlinebreak case sceneRENDER_MODE_VERTICES currender=Verticesbreak case sceneRENDER_MODE_SHADED_VERTICES currender=ShadedVerticesbreak case sceneRENDER_MODE_WIREFRAME currender=Wireframebreak case sceneRENDER_MODE_SHADED_WIREFRAME currender=ShadedWireframebreak case sceneRENDER_MODE_SOLID currender=Solidbreak case sceneRENDER_MODE_TRANSPARENT currender=Transparentbreak case sceneRENDER_MODE_SOLID_WIREFRAME currender=SolidWireframebreak case sceneRENDER_MODE_TRANSPARENT_WIREFRAME currender=TransparentWireframebreak case sceneRENDER_MODE_ILLUSTRATION currender=Illustrationbreak case sceneRENDER_MODE_SOLID_OUTLINE currender=SolidOutlinebreak case sceneRENDER_MODE_SHADED_ILLUSTRATION currender=ShadedIllustrationbreak case sceneRENDER_MODE_HIDDEN_WIREFRAME currender=HiddenWireframebreak case sceneRENDER_MODE_DEFAULT currender=Defaultbreak if(currender=defaultrender) respart+= RENDERMODE=+currender+n defaultvals=false if(origtrans[ndname]ampampndtransformisEqual(origtrans[ndname])) var lvec=ndtransformtransformDirection(new Vector3(100)) var uvec=ndtransformtransformDirection(new Vector3(010)) var vvec=ndtransformtransformDirection(new Vector3(001)) respart+= TRANSFORM= +lvecx+ +lvecy+ +lvecz+ +uvecx+ +uvecy+ +uvecz+ +vvecx+ +vvecy+ +vvecz+ +ndtransformtranslationx+ +ndtransformtranslationy+ +ndtransformtranslationz+n defaultvals=false respart+= ENDn if(defaultvals) res+=respart if(clip) var centre=cliptransformtranslation var normal=cliptransformtransformDirection(new Vector3(001)) res+= CROSSSECTn if((centrex==0 ampamp centrey==0 ampamp centrez==0)) res+=hostutilprintf( CENTER=s s sn centrex centrey centrez) if((normalx==1 ampamp normaly==0 ampamp normalz==0)) res+=hostutilprintf( NORMAL=s s sn normalx normaly normalz) res+=hostutilprintf( VISIBLE=sn clipvisible) res+=hostutilprintf( PLANECOLOR=s s sn clipmaterialemissiveColorr clipmaterialemissiveColorg clipmaterialemissiveColorb) res+=hostutilprintf( OPACITY=sn clipopacity) res+=hostutilprintf( INTERSECTIONCOLOR=s s sn clipwireframeColorr clipwireframeColorg clipwireframeColorb) res+= ENDn for(var propt in clip) consoleprintln(propt++clip[propt]) res+=ENDn hostconsoleshow() hostconsoleclear() hostconsoleprintln(n Add the following VIEW section to a file ofn+ predefined views (See option 3Dviews)nn + The view may be given a name after VIEW=n + (Remove in front of =)n) hostconsoleprintln(res + n)add items to 3D context menuruntimeaddCustomMenuItem(dfltview Generate Default View default 0)runtimeaddCustomMenuItem(currview Get Current View default 0)runtimeaddCustomMenuItem(csection Cross Section checked 0)menu event handlersmenuEventHandler = new MenuEventHandler()menuEventHandleronEvent = function(e) switch(emenuItemName) case dfltview calc3Dopts() break case currview get3Dview() break case csection addremoveClipPlane(emenuItemChecked) break runtimeaddEventHandler(menuEventHandler)global variable taking reference to currently selected nodevar target=nullselectionEventHandler=new SelectionEventHandler()selectionEventHandleronEvent=function(e) if(eselectedampampenodename=) target=enode else target=null runtimeaddEventHandler(selectionEventHandler)cameraEventHandler=new CameraEventHandler()cameraEventHandleronEvent=function(e) var clip=null runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 0) if(clip=scenenodesgetByName($$$$$$)|| predefined scenenodesgetByName(Clipping Plane)) added via context menu runtimeremoveCustomMenuItem(csection) runtimeaddCustomMenuItem(csection Cross Section checked 1) if(clip)plane in predefined views must be rotated by 90 deg around normal cliptransformrotateAboutLineInPlace( MathPI2cliptransformtranslation cliptransformtransformDirection(new Vector3(001)) ) for(var i=0 iltrot4x4length i++)rot4x4[i]setIdentity() target=nullruntimeaddEventHandler(cameraEventHandler)var rot4x4=new Array() keeps track of spin and tilt axes transformationskey event handler for scaling moving spinning and tilting objectskeyEventHandler=new KeyEventHandler()keyEventHandleronEvent=function(e) var backtrans=new Matrix4x4() var trgt=null if(target) trgt=target var backtrans=new Matrix4x4() var trans=trgttransform var parent=trgtparent while(parenttransform) build local to world transformation matrix transmultiplyInPlace(parenttransform) also build world to local back-transformation matrix backtransmultiplyInPlace(parenttransforminversetranspose) parent=parentparent backtranstransposeInPlace() else if( trgt=scenenodesgetByName($$$$$$)|| trgt=scenenodesgetByName(Clipping Plane) ) var trans=trgttransform if(trgt) return var tname=trgtname if(typeof(rot4x4[tname])==undefined) rot4x4[tname]=new Matrix4x4() if(target) var tiltAxis=rot4x4[tname]transformDirection(new Vector3(010)) else var tiltAxis=transtransformDirection(new Vector3(010)) var spinAxis=rot4x4[tname]transformDirection(new Vector3(001)) get the centre of the mesh if(targetampamptrgtconstructorname==Mesh) var centre=transtransformPosition(trgtcomputeBoundingBox()center) else part group (Node3 parent node clipping plane) var centre=new Vector3(transtranslation) switch(echaracterCode) case 30tilt up rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(-MathPI900centretiltAxis) break case 31tilt down rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationtiltAxis) transrotateAboutLineInPlace(MathPI900centretiltAxis) break case 28spin right if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(-MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( -MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(-MathPI900centrenew Vector3(001)) break case 29spin left if(ectrlKeyDownampamptarget) transrotateAboutLineInPlace(MathPI900centrespinAxis) else rot4x4[tname]rotateAboutLineInPlace( MathPI900rot4x4[tname]translationnew Vector3(001)) transrotateAboutLineInPlace(MathPI900centrenew Vector3(001)) break case 120 x translateTarget(trans new Vector3(100) e) break case 121 y translateTarget(trans new Vector3(010) e) break case 122 z translateTarget(trans new Vector3(001) e) break case 88 shift + x translateTarget(trans new Vector3(-100) e) break case 89 shift + y translateTarget(trans new Vector3(0-10) e) break case 90 shift + z translateTarget(trans new Vector3(00-1) e) break case 115 s transtranslateInPlace(centrescale(-1)) transscaleInPlace(101) transtranslateInPlace(centrescale(1)) break case 83 shift + s transtranslateInPlace(centrescale(-1)) transscaleInPlace(1101) transtranslateInPlace(centrescale(1)) break transmultiplyInPlace(backtrans)runtimeaddEventHandler(keyEventHandler)translates object by amount calculated from Canvas sizefunction translateTarget(t d e) var cam=scenecamerasgetByIndex(0) if(camprojectionType==camTYPE_PERSPECTIVE) var scale=Mathtan(camfov2) camtargetPositionsubtract(camposition)length Mathmin(ecanvasPixelWidthecanvasPixelHeight) else var scale=camviewPlaneSize2 Mathmin(ecanvasPixelWidthecanvasPixelHeight) ttranslateInPlace(dscale(scale))function addremoveClipPlane(chk) var curTrans=getCurTrans() var clip=scenecreateClippingPlane() if(chk) add Clipping Plane and place its center either into the camera target position or into the centre of the currently selected mesh node var centre=new Vector3() if(target) var trans=targettransform var parent=targetparent while(parenttransform) trans=transmultiply(parenttransform) parent=parentparent if(targetconstructorname==Mesh) var centre=transtransformPosition(targetcomputeBoundingBox()center) else var centre=new Vector3(transtranslation) target=null else centreset(scenecamerasgetByIndex(0)targetPosition) cliptransformsetView( new Vector3(000) new Vector3(100) new Vector3(010)) cliptransformtranslateInPlace(centre) else if( scenenodesgetByName($$$$$$)|| scenenodesgetByName(Clipping Plane) ) clipremove()clip=null restoreTrans(curTrans) return clipfunction to store current transformation matrix of all nodes in the scenefunction getCurTrans() var tA=new Array() for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(ndname==) continue tA[ndname]=new Matrix4x4(ndtransform) return tAfunction to restore transformation matrices given as argfunction restoreTrans(tA) for(var i=0 iltscenenodescount i++) var nd=scenenodesgetByIndex(i) if(tA[ndname]) ndtransformset(tA[ndname]) store original transformation matrix of all mesh nodes in the scenevar origtrans=getCurTrans()set initial state of Cross Section menu entrycameraEventHandleronEvent(1)hostconsoleclear()

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 35: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

72 3D quick-start guide1 Insert the 3D object with default camera settings and with extended context

menu enabled (option lsquo3Dmenursquo)

includemedia[width=05linewidthheight=05linewidthactivate=pageopen3Dmenu

]myfileu3d

2 Compile the document

3 Open the PDF document in Adobe Reader and go to the page containing the 3Dobject Select lsquoGenerate Default Viewrsquo from the 3D context menu (right mouseclick) and wait for the JavaScript console to pop up Optionally drag the objectwith the mouse to change the viewpoint of the camera and select lsquoGenerateDefault Viewrsquo again This will re-adjust the distance between camera and targetto t all visible parts tightly into the viewport The options printed into theconsole are updated accordingly

4 Copy the camera settings (3Droo= 3Dcoo= etc) from the console intothe option list of includemedia

5 Compile the document again

Optional steps (option lsquo3Dmenursquo required)

6 Additional named views cross sections rescaled repositioned parts

a) Open a text le e g lsquomyviewsvwsrsquo to be populated with additional viewsof the 3D object

b) Manipulate the 3D object using the mouse (camera position) and via 3Dcontext menu items lsquoPart Optionsrsquo and lsquoViewing Optionsrsquo (visibility render-ing attributes background etc) the camera target can be moved into thecentre of a single part via lsquoPart OptionsrsquorarrlsquoZoom to Partrsquo

c) Add a cross section plane (select lsquoCross Sectionrsquo from the 3D context menu)adjust its position using the keyboard keyboard keys are given here

d) Adjust scaling and position of individual parts using the keyboard key-board keys are given here

e) Re-adjust the camera distance using either lsquoGenerate Default Viewrsquo or lsquoPartOptionsrsquorarrlsquoFit Visiblersquo

f) When you are done select lsquoGet Current Viewrsquo to get the VIEW sectionreadily formatted for insertion into the views le Repeat steps (a)ndash(f) toget any number of views you want to dene The views le can be editedmanually to give meaningful names to the views (change the value of theVIEW key) or to further tweak camera settings opacity part options etc

g) Attach the views le with option lsquo3Dviewsrsquo

includemedia[width=05linewidthheight=05linewidth

35

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 36: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

activate=pageopen3Dviews=myviewsvws3Dmenu

]myfileu3d

If you are satised with the predened views in the views le the defaultview rst specied through the options of includemedia can be deletedThe rst view in the views le becomes the default view then

7 Associate any number of 3D JavaScript les with the 3D object

includemedia[width=05linewidthheight=05linewidthactivate=pageopenadd3Djscript=somescriptjsadd3Djscript=otherscriptjs3Dviews=myviewsvws3Dmenu

]myfileu3d

A few 3D JavaScript les ready to be used are already installed along withlsquomedia9styrsquo see above

8 Caveats1 Large media les may cause TEX to interrupt with error

TeX capacity exceeded sorry [main memory size=3000000]

when using latex in dvips mode While writing the DVI le media les inthe current page that are about to be embedded are kept in TEXrsquos memory untilshipping out of the readily typeset page In the case of large or many les thismay be more than TEX can cope with by default

There are two options to handle such situations

The rst one is to increase TEXrsquos main memory You may follow the steps inthe Bugs section of the lsquoanimatersquo package documentation In TEXLive-2012 themaximum value that can be set is main_memory = 12435455

If increasing TEXrsquos main memory does not help use the package option lsquobigfilesrsquowith media9 It defers le embedding from the DVI producing to the PS producingstep

2 In right-to-left typesetting context (RTL) using the (pdf)LATEX or X ELATEX enginesthe ltposter textgt argument of includemedia and the text arguments forbutton faces of the mediabutton command should be enclosed in pairs ofbeginR and endR

9 AcknowledgementsThis package was written using the new LATEX3 syntax which was a lot of fun Manythanks to the LATEX3 team

36

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00
Page 37: The media9 Package - ConcertPass.com Mirror Servermirrors.concertpass.com/tex-archive/macros/latex/contrib/media9/... · 1 Introduction This package provides an interface to embed,

References[1] Adobe Systems Inc Strobe Media Playback 2010 available at httposmforg

strobe_mediaplaybackhtml

[2] Adobe Systems Inc Adobe Supplement to ISO 32000 BaseVersion 17 Extension-Level 3 2008 available at httpwwwimagesadobecomwwwadobecomcontentdamAdobeendevnetpdfpdfsadobe_supplement_iso32000pdf

[3] Adobe Systems Inc JavaScript for Acrobat 3D Annotations API Reference availableat httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_3D_Intro901html

[4] Adobe Systems Inc JavaScript for Acrobat API Reference available athttplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpJS_API_AcroJSPreface871html

[5] The Apache Software Foundation Apache Flex SDK available at httpflexapacheorg

[6] ECMA International Universal 3D File Format (ECMA-363) 4th Edition 2007available at httpwwwecma-internationalorgpublicationsfilesECMA-STECMA-363204th20Editionpdf

[7] Adobe Systems Inc PRC Format Specication available at httplivedocsadobecomacrobat_sdk10Acrobat10_HTMLHelpAPI_ReferencesPRCReferencePRC_Format_Specificationindexhtml

[8] A Hammerlindl J Bowman and T Prince Asymptote The Vector Graphics Lan-guage available at httpasymptotesourceforgenet

[9] A A Balakin MathGL - library for scientic graphics available at httpmathglsourceforgenet

[10] T OrsquoRourke T Strelchun Universal 3D Sample Software available at httpsourceforgenetprojectsu3d

[11] P Cignoni et al MeshLab available at httpmeshlabsourceforgenet

[12] RightHemisphere Inc DeepExploration httpwwwrighthemispherecomproductsdexp

37

  • 1 Introduction
  • 2 Requirements
  • 3 Installation
  • 4 Using the package
  • 5 The user interface
    • 51 Media inclusion
    • 52 Command options
    • 53 Control buttons
      • 6 Embedding Flash video and sound image slide-shows (with examples)
      • 7 Embedding 3D objects (with examples)
        • 71 Introduction
        • 72 3D quick-start guide
          • 8 Caveats
          • 9 Acknowledgements
              1. mbtn14
              2. mbtn13
              3. mbtn12
              4. mbtn11
              5. mbtn10
              6. mbtn9
              7. fdmalte
              8. mbtn8
              9. mbtn7
              10. mbtn6
              11. fddice
              12. fdrm9
              13. fdrm8
              14. fdrm7
              15. mbtn5
              16. mbtn4
              17. mbtn3
              18. fdsong49
              19. fdrm5
              20. fdrm4
              21. fdrm3
              22. fdrm2
              23. mbtn2
              24. mbtn1
              25. mbtn0
              26. fdsome_dice
              27. fdrm0
              28. anm0
              29. 01
              30. 00