.. |homeicon| image:: homeicon.png

###########
Defining 3D
###########

In the PDF world, the 3D data is called a 3D Annotation. It is composed of a 3D model called 3D Artwork and of options for the Adobe Reader. The 3D model can be created from a CAD file, or it can also be entirely created with the Advanced Publishing API and the creation functions. The 3D Annotation may define 3D Views to define a point of view on the 3D model (a camera).

3D Stream
=========

The 3D Stream is the basic definition for the 3D data. It is a binary stream where relies the definition of the 3D. The stream can be obtained from a A3DAsmModelFile object, or can directly come from a file.


3D Stream From a Model File
---------------------------

An A3DAsmModelFile is an entity which defines the 3D model. An A3DAsmModelFile can be obtained from a CAD file with the function A3DAsmModelFileLoadFromFile. Note that in this case, the CAD model is parsed and translated in a Model File format, which is basically the PRC format. That way, if a data is not supported in the PRC format, it will be lost during the conversion. Additionally, Advanced Publishing also provides a full API to create the Model File. Once created, the Model File can be stored as a 3D Stream in a PRC or in a U3D format. Use A3DPDF3DStreamCreateFromModelFileAsPRC or A3DPDF3DStreamCreateFromModelFileAsU3D.

.. code-block:: c

    A3DRWParamsLoadData sReadParam = A3D_MAKE_DATA(A3DRWParamsLoadData);
    sReadParam.m_sGeneral.m_bReadSolids = true;
    sReadParam.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
    sReadParam.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown;
    sReadParam.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
    A3DAsmModelFile* pModelFile = NULL;
    iRet = A3DAsmModelFileLoadFromFile("c:\\temp\\my3d.prc", &sReadParam, &pModelFile);
    A3DRWParamsExportPrcData sParamsExportData = A3D_MAKE_DATA(A3DRWParamsExportPrcData);
    sParamsExportData.m_bCompressBrep = true;
    A3DPDF3DStream* pStream = NULL;
    iRet = A3DPDF3DStreamCreateFromModelFileAsPRC(pDoc,
                                                  pModelFile,
                                                  &sParamsExportData,
                                                  &pStream,
                                                  NULL);


3D Stream From a File
---------------------

A 3D Stream can also be defined directly from a file, without any parsing or translation phase. In this case, the file is read and stored as-is in the 3D Stream. This is a good solution if the file contains data not supported by the PRC format. For example, this is the only way to keep the animations defined in a U3D file.

.. code-block:: c

    A3DPDF3DStream* pStream = NULL;
    iRet = A3DPDF3DStreamCreateFromFile(pDoc, "c:\\temp\\my3dwithanimations.u3d", false, &pStream);


3D Artwork
==========

The 3D Artwork is an intermediary structure holding a 3D Stream. A JavaScript can also be specified, it will be run every time the 3D annotation is activated in the Adobe Reader. This JavaScript typically defines some functions to be called in other parts of the PDF (such as buttons). A JavaScript is mandatory in certain use cases, such as with a U3D file with animations: here the JavaScript has to define the runtime engine for the animation. A 3D Artwork might also define some 3D Views (see below).

.. code-block:: c

    A3DPDF3DArtworkData2 s3DArtworkData = A3D_MAKE_DATA(A3DPDF3DArtworkData2);
    s3DArtworkData.m_pStream = p3DStream;
    s3DArtworkData.m_sDisplaySectionData.m_bAddSectionCaps = true;
    s3DArtworkData.m_pcJavaScriptFileName = "c:\\temp\\myscript.js";
    s3DArtworkData.m_eAnimationStyle = kA3DPDFAnimStyleNoAnimation;
    A3DPDF3DArtwork* p3DArtwork = NULL;
    iRet = A3DPDF3DArtworkCreate2(pDoc, &s3DArtworkData, &p3DArtwork);


3D Annotation
=============

The 3D Annotation is the real 3D object to be stored in the PDF. It contains the 3D Artwork where the 3D is defined, as well as a set of options used by the Adobe Reader when playing the PDF. Also, the 3D Annotation may define a ’poster’: an image to be displayed when the 3D is not activated. By default, if no poster file is specified, Advanced Publishing automatically calculates one from the default view of the 3D model. If your workflow already calculates a poster, an image file can be specified. Also, if you feel the PDF doesn’t need a poster (the 3D should always be activated), the best is to specify a blank poster (a sample is provided in the package: blank.bmp). To create a 3D Annotation object, use A3DPDF3DAnnotCreate.

.. code-block:: c

    A3DPDF3DAnnotData sAnnotData = A3D_MAKE_DATA(A3DPDF3DAnnotData);
    sAnnotData.m_bOpenModelTree = false;
    sAnnotData.m_bShowToolbar = false;
    sAnnotData.m_eLighting = kA3DPDFLightCADOptimized;
    sAnnotData.m_eRenderingStyle = kA3DPDFRenderingSolid;
    sAnnotData.m_sBackgroundColor.m_dRed = 0.25;
    sAnnotData.m_sBackgroundColor.m_dGreen = 0.25;
    sAnnotData.m_sBackgroundColor.m_dBlue = 0.25;
    sAnnotData.m_bTransparentBackground = false;
    sAnnotData.m_eActivateWhen = kA3DPDFActivExplicitActivation;
    sAnnotData.m_eDesactivateWhen = kA3DPDFActivPageClosed;
    sAnnotData.m_iAppearanceBorderWidth = 0;
    // no poster specified: default poster automatically generated
    //sAnnotData.m_pPosterImage = pImage;
    sAnnotData.m_p3DArtwork = p3DArtwork;
    A3DPDF3DAnnot* p3DAnnot = NULL;
    iRet = A3DPDF3DAnnotCreate(pDoc, &sAnnotData, &p3DAnnot);


Activating PMI Cross-Highlighting
---------------------------------

PMI cross-highlighting is the ability for the end user to click on a markup in order to find the associated geometry. Advanced Publishing can be used to generate some JavaScript code that reproduces this behavior. This feature is using JavaScript functionality only available on Acrobat XI and later versions. Moreover, it is only working on geometry defined as surfaces.

.. code-block:: c

    s3DArtworkData.m_bActivatePMICrossHighlight = true;


Inserting a 3D Annotation in a Page
-----------------------------------

You can insert a 3D Annotation object in a page. The 3D can be positioned anywhere on the page, specified by a rectangle in page unit, from the bottom left of the page. To insert a 3D Annotation object use A3DPDFPageInsert3DAnnot.

.. code-block:: c

    A3DPDFRectData sPos = A3D_MAKE_DATA(A3DPDFRectData);
    // coordinates are from bottom left of the page
    sPos.m_iLeft = 150;                // lower left x
    sPos.m_iBottom = 100;              // lower left y
    sPos.m_iRight = iPageWidth - 150;  // upper right x
    sPos.m_iTop = iPageHeight - 145;   // upper right y
    iRet = A3DPDFPageInsert3DAnnot(pPage, p3DAnnot, &sPos);


Setting a 3D Annotation on a Field
----------------------------------

The 3D Annotation object can also be stored in the place of a field on the page. Here the field is only used to specify the positioning in the page. By convention, the field must be a button field. To replace a field with a 3D Annotation object use A3DPDFPageFieldSet3DAnnot. Note that the field is really replaced and will be removed from the page.

.. code-block:: c

    iRet = A3DPDFPageFieldSet3DAnnot(pPage, "My3DWindow", p3DAnnot);


3D Views
========

A 3D view specifies parameters that shall be applied to the virtual camera associated with a 3D Annotation. These parameters include the definition of the camera (position, orientation, projection mode), as well as display settings to specify how 3D artwork is rendered, colored, and lit. Views may also specify which nodes of 3D artwork shall be included in a view and whether those nodes are opaque or invisible.

The views can be activated interactively by the end user with the Adobe Reader toolbar buttons, or can also be programmatically activated at runtime with a JavaScript piece of code. This JavaScript can be stored on a button.

The views available in a 3D PDF can have different origins:

    * the **Native views** are defined natively in the original CAD file, or programmatically with the PRC structure ``A3DMkpViewData``. They define the whole set of functionalities available for views (camera, nodes visibility and different attributes, cross sections, ...). Native views are automatically transformed in views in the PDF scene by Advanced Publishing when the 3D annot is inserted on the page.
    * **Advanced Publishing views** are programmatically created with Advanced Publishing functions and just define a camera and display parameters. Use A3DPDFViewCreate to create the view and A3DPDF3DArtworkAddView to store it in the 3D Artwork.
    * an **Automatic view** is automatically created by Advanced Publishing if no default view is specified in the 3D. See section below.


Default View
------------

The default view in a PDF document is the view displayed when the 3D is activated. The default view is represented in Adobe Reader with a ’home’ icon |homeicon|. Any **Native view** or **Advanced Publishing view** can be set as default. If none are defined, Advanced Publishing automatically creates a new default view: the **Automatic view**. The Automatic view is associated with the ’home’ icon but is not displayed in the list of the views of the toolbar.

A **Native view** is set as default by setting the boolean ``A3DMkpViewData.m_bIsDefaultView`` to true. A **Advanced Publishing view** can be set as default by setting the boolean ``A3DPDFViewData.m_bIsDefault`` to true. Ideally, only one view should be set as default. If several are, Advanced Publishing uses the first one as default. If no default view is defined, Advanced Publishing creates the **Automatic view**. Advanced Publishing 6.0 introduces a new parameter ``A3DPDF3DArtworkData2.m_bKeepNativeDefaultView`` to better control which view should be used at default. As a sum-up, you can consider that if your 3D defines the views, it is better to set m_bKeepNativeDefaultView to true and let Advanced Publishing go: it will use the predefined native default view if any, and will create a new one if no view is default. If you prefer to define your own views that would overload any predefined native default view, set m_bKeepNativeDefaultView to false and use the PDF views creation functions to define your view.


View Display Settings
---------------------

The display for a 3D view is controlled by **Display Settings**. Display settings are the background color, the lighting effect, and the rendering mode. Display settings behavior is as follows: Initially when the 3D PDF is opened, the view activated is the default view and settings for the default view are applied. Then, another view can be activated by the end user. This alternate view can have different specific display parameters, or can use the same default settings as the default view. Finally, the end user has the possibility to use the Adobe reader toolbar to manually define runtime display settings to be used during the current viewing session. Whether these manual settings should be used for all views or not is an option that can be set using Advanced Publishing.

The whole display settings behavior can be defined using Advanced Publishing parameters.


Display Settings for the Default View
-------------------------------------

The settings for the default view differ depending on the type of the default view:

    * If the default view is a **native view**: the settings are defined on ``A3DPDF3DAnnotData``  with the m_sBackgroundColor, m_eLighting, and m_eRenderingStyle members.
    * If the default view is a **Advanced Publishing view**: display settings are defined on ``A3DPDFViewData`` with the m_sViewBackgroundColor, m_eViewLighting, and m_eViewRenderingStyle members. They need to be defined for each Advanced Publishing view and thus they can differ for each view.
    * If the default view is the **automatic view**: display settings are defined with ``A3DPDF3DAnnotData`` and m_sBackgroundColor, m_eLighting, and m_eRenderingStyle members.


Display Settings for the Non-Default Views
------------------------------------------

The settings for the non-default views depend on the Boolean ``A3DPDF3DArtworkData2.m_bUseRuntimeDisplaySettings`` and the type of the views. If the Boolean ``A3DPDF3DArtworkData2.m_bUseRuntimeDisplaySettings`` is true, the non-default views take the last values defined at runtime: initially the default values (``A3DPDF3DAnnotData`` members), or later the values manually defined by the end user if he did so. If m_bUseRuntimeDisplaySettings is false, all the non-default **native views** have the same default display settings (``A3DPDF3DAnnotData`` members); whereas each non-default **Advanced Publishing view** can have different display settings values defined with ``A3DPDFViewData`` members.


Camera Definition
-----------------

A camera is what allows to view a scene. It consists of several components.

    **Position:**
    The position of the camera is a point that represents the position of the viewpoint. Normally, the camera position is placed slightly away from the objects that you wish to view (see note below).

    **Target:**
    The target is a point toward which the camera is looking. The camera target is usually in the middle of the objects that you wish to view. The camera target must not be at the same position as the camera. The vector between the camera position and the camera target is called the line of sight.

    **Up vector:**
    The up vector is a vector that defines "which way is up." If you specified only the camera’s position and target, the camera could still rotate around the line of sight, so the up vector fixes the orientation of the camera. The up vector must not be all zeros, and cannot be parallel to the line of sight. The up vector should be perpendicular to the line of sight. If not, the resulting view in the PDF file will act strangely when triggered (usually slightly jumping).

    **Projection:**
    The projection determines how to represent the 3D coordinates of a scene using only the 2D coordinates on the screen. A perspective projection scales the x and y coordinates depending on the z coordinate, such that objects that are farther away appear smaller on the screen. In an orthographic projection, the direction of projection is perpendicular to the camera target plane (so, the x and y coordinates aren’t scaled).

    **View Size:**
    The view size defines the minimum area around the target that will be visible in the PDF reader. For a **perspective** projection, it is specified with the argument m_dFieldOfView, as a field of view angle in degrees. Note that the field of view changes what can be seen on the screen, but also distorts the scene. For an **orthographic** projection, the view size is specified through the m_dZoomFactor argument. The zoom factor is related to the view size with: zoomfactor = 1/2 * view_size, with view_size as the smallest size of the viewable part in the X or Y direction.

**Important note:** The position of the camera must be defined far enough from the target. If not, the user will notice some unexpected clipping problems when rotating the model. If we see the model as a rectangular box, the distance between Position and Target should be greater than the largest of the rectangular box dimension. This rule applies for camera defined with the ``A3DPDFViewData`` structure, as well as camera calculated from a ``A3DGraphCameraData`` structure (being defined from a native view, or programatically with the HOOPS Exchange API).


Functions on Views
------------------

**Advanced Publishing views** are programmatically created with Advanced Publishing functions and just define a camera and display parameters. Use A3DPDFViewCreate to create the view and A3DPDF3DArtworkAddView to store it in the 3D Artwork.

.. code-block:: c

    A3DPDFViewData sViewData = A3D_MAKE_DATA(A3DPDFViewData);
    sViewData.m_sPosition.m_dX = dPosX;
    sViewData.m_sPosition.m_dY = dPosY;
    sViewData.m_sPosition.m_dZ = dPosZ;
    sViewData.m_sTarget.m_dX = dTargetX;
    sViewData.m_sTarget.m_dY = dTargetY;
    sViewData.m_sTarget.m_dZ = dTargetZ;
    sViewData.m_sUpVector.m_dX = 0;
    sViewData.m_sUpVector.m_dY = 0;
    sViewData.m_sUpVector.m_dZ = 1;
    sViewData.m_eProjectionMode = kA3DPDFPerspectiveMode;
    sViewData.m_dFieldOfView = dFieldOfView;  // only valid for perspective projection
    sViewData.m_bIsDefault = bIsDefault;
    sViewData.m_pcExternalName = pcViewName;
    sViewData.m_sViewBackgroundColor.m_dBlue = 1.0;
    sViewData.m_sViewBackgroundColor.m_dGreen = 1.0;
    sViewData.m_sViewBackgroundColor.m_dRed = 1.0;
    sViewData.m_eViewLighting = kA3DPDFLightCADOptimized;
    sViewData.m_eViewRenderingStyle = kA3DPDFRenderingSolid;
    A3DPDFView* pView = NULL;
    iRet = A3DPDFViewCreate(pDoc, &sViewData, &pView);
    iRet = A3DPDF3DArtworkAddView(p3DArtwork, *ppView);

Advanced Publishing has functions to get the identifiers of all the type of views (native views, Advanced Publishing views, and the automatic view if any). These identifiers might be used in a JavaScript code to activate the view.

.. code-block:: c

    // getting view IDs as stored in the original file
    A3DUns32 uiNbViews;
    A3DPDFView** ppViews;
    iRet = A3DPDF3DArtworkGetViews(p3DArtwork, &uiNbViews, &ppViews);
    // parsing the views to get the identifier.
    for (A3DUns32 ui = 0; ui < uiNbViews; ++ui)
    {
        A3DUTF8Char* pcViewId = NULL;
        A3DPDFViewGetExternalName(ppViews[ui], &pcViewId);
        // building the JavaScript command to activate the view
        char jscmd[1024];
        sprintf(jscmd, "c3d = this.getAnnots3D( 0 )[0].context3D;c3d.runtime.setView(\"%s\", false);", pcViewId);
    }


3D Poster
=========

Advanced Publishing has a function to generate a poster from a selected view of the 3D data. Use A3DPDFMakeSnapshotFromModelFile to generate the poster from the model file object. The image format is specified by the filename extension. The dimensions are in pixels and the resolution is 72 pixels per inch.

.. code-block:: c

    A3DPDFSnapshotOptionsData sOptionData = A3D_MAKE_DATA(A3DPDFSnapshotOptionsData);
    sOptionData.m_iWidth = width;
    sOptionData.m_iHeight = height;
    sOptionData.m_pView = pView;
    iRet = A3DPDFMakeSnapshotFromModelFile(pModelFile,
                                           &sOptionData,
                                           "c:\\temp\\mygeneratedposter.jpg");
