> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/get-started/samples/u3dtest.md).

# Embed 3D Models (U3D) in PDF

Sample code for using Apryse SDK to embed U3D content (3 dimensional models) in PDF files, provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.

Sample code for using Apryse SDK to embed U3D content (3 dimensional models) in PDF files. Sample code provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.

Learn more about our [Server SDK](/core/get-started/get-started.md).

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
//

using System;
using pdftron;
using pdftron.Common;
using pdftron.Filters;
using pdftron.SDF;
using pdftron.PDF;

namespace U3DTestCS
{
	/// <summary>
	/// This example illustrates how to embed U3D content in PDF. 
	/// Some parameters used to center 3D model are assumed.
	/// </summary>
	class Class1
	{
		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
		static Class1() {}

		// Relative path to the folder containing test files.
		const string input_path =  "../../../../TestFiles/";
		const string output_path = "../../../../TestFiles/Output/";

		static void Main(string[] args)
		{
			PDFNet.Initialize(PDFTronLicense.Key);

			try  
			{	 
				using (PDFDoc doc = new PDFDoc())
				{
					Page page = doc.PageCreate();
					doc.PagePushBack(page);
					Obj annots = doc.CreateIndirectArray();
					page.GetSDFObj().Put("Annots", annots);

					Create3DAnnotation(doc, annots);
					doc.Save(output_path + "dice_u3d.pdf", SDFDoc.SaveOptions.e_linearized);
				}
				Console.WriteLine("Done");
			}
			catch (PDFNetException e)
			{
				Console.WriteLine(e.Message);
			}
			PDFNet.Terminate();
		}

		static void Create3DAnnotation(PDFDoc doc, Obj annots)
		{
			// ---------------------------------------------------------------------------------
			// Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
			// for collections of three-dimensional objects, such as those used by CAD software, 
			// to be embedded in PDF files.
			Obj link_3D = doc.CreateIndirectDict();
			link_3D.PutName("Subtype", "3D");

			// Annotation location on the page
			Rect bbox = new Rect(25, 180, 585, 643);
			link_3D.PutRect("Rect", bbox.x1, bbox.y1, bbox.x2, bbox.y2);
			annots.PushBack(link_3D);

			// The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
			// that determines how the state of the annotation and its associated artwork can change.
			Obj activation_dict_3D = link_3D.PutDict("3DA");

			// Set the annotation so that it is activated as soon as the page containing the 
			// annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
			activation_dict_3D.PutName("A", "PO");

			// Embed U3D Streams (3D Model/Artwork).
			MappedFile u3d_file = new MappedFile(input_path + "dice.u3d");
			FilterReader u3d_reader = new FilterReader(u3d_file);

			Obj u3d_data_dict = doc.CreateIndirectStream(u3d_reader);
			u3d_data_dict.PutName("Subtype", "U3D");
			link_3D.Put("3DD", u3d_data_dict);

			// Set the initial view of the 3D artwork that should be used when the annotation is activated.
			Obj view3D_dict = link_3D.PutDict("3DV");			
			view3D_dict.PutString("IN", "Unnamed");
			view3D_dict.PutString("XN", "Default");
			view3D_dict.PutName("MS", "M");
			view3D_dict.PutNumber("CO", 27.5);

			// A 12-element 3D transformation matrix that specifies a position and orientation 
			// of the camera in world coordinates.
			Obj tr3d = view3D_dict.PutArray("C2W");
			tr3d.PushBackNumber(1); tr3d.PushBackNumber(0); tr3d.PushBackNumber(0); 
			tr3d.PushBackNumber(0); tr3d.PushBackNumber(0); tr3d.PushBackNumber(-1);
			tr3d.PushBackNumber(0); tr3d.PushBackNumber(1); tr3d.PushBackNumber(0); 
			tr3d.PushBackNumber(0); tr3d.PushBackNumber(-27.5); tr3d.PushBackNumber(0);			

			// Create annotation appearance stream, a thumbnail which is used during printing or
			// in PDF processors that do not understand 3D data.
			Obj ap_dict = link_3D.PutDict("AP");
			ElementBuilder builder = new ElementBuilder();
			ElementWriter writer = new ElementWriter();
			writer.Begin(doc);

			writer.WritePlacedElement(builder.CreateImage(
				Image.Create(doc, input_path + "dice.jpg"), 
					   0, 0, bbox.Width(), bbox.Height()));

			Obj normal_ap_stream = writer.End();
			normal_ap_stream.PutName("Subtype", "Form");
			normal_ap_stream.PutRect("BBox", 0, 0, bbox.Width(), bbox.Height());
			ap_dict.Put("N", normal_ap_stream);
		}
	}
}
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#include <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <PDF/ElementWriter.h>
#include <PDF/ElementBuilder.h>
#include <SDF/Obj.h>
#include <Filters/MappedFile.h>
#include <Filters/FilterReader.h>
#include <Filters/FlateEncode.h>
#include <iostream>
#include "../../LicenseKey/CPP/LicenseKey.h"

using namespace pdftron;
using namespace Filters;
using namespace SDF;
using namespace PDF;
using namespace std;

std::string input_path =  "../../TestFiles/";

void Create3DAnnotation(PDFDoc& doc, Obj annots)
{
	// ---------------------------------------------------------------------------------
	// Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
	// for collections of three-dimensional objects, such as those used by CAD software, 
	// to be embedded in PDF files.
	Obj link_3D = doc.CreateIndirectDict();
	link_3D.PutName("Subtype", "3D");

	// Annotation location on the page
	Rect link_3D_rect(25, 180, 585, 643);
	link_3D.PutRect("Rect", link_3D_rect.x1, link_3D_rect.y1,
		link_3D_rect.x2, link_3D_rect.y2);
	annots.PushBack(link_3D);

	// The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
	// that determines how the state of the annotation and its associated artwork can change.
	Obj activation_dict_3D = link_3D.PutDict("3DA");

	// Set the annotation so that it is activated as soon as the page containing the 
	// annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
	activation_dict_3D.PutName("A", "PO");  

	// Embed U3D Streams (3D Model/Artwork).
	{
		MappedFile u3d_file((input_path + "dice.u3d"));
		FilterReader u3d_reader(u3d_file);

		// To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
		Obj u3d_data_dict = doc.CreateIndirectStream(u3d_reader, FlateEncode(Filter()));
		u3d_data_dict.PutName("Subtype", "U3D");
		link_3D.Put("3DD", u3d_data_dict);
	}

	// Set the initial view of the 3D artwork that should be used when the annotation is activated.
	Obj view3D_dict = link_3D.PutDict("3DV");
	{
		view3D_dict.PutString("IN", "Unnamed");
		view3D_dict.PutString("XN", "Default");
		view3D_dict.PutName("MS", "M");
		view3D_dict.PutNumber("CO", 27.5);

		// A 12-element 3D transformation matrix that specifies a position and orientation 
		// of the camera in world coordinates.
		Obj tr3d = 	view3D_dict.PutArray("C2W"); 
		tr3d.PushBackNumber(1); tr3d.PushBackNumber(0); tr3d.PushBackNumber(0); 
		tr3d.PushBackNumber(0); tr3d.PushBackNumber(0); tr3d.PushBackNumber(-1);
		tr3d.PushBackNumber(0); tr3d.PushBackNumber(1); tr3d.PushBackNumber(0); 
		tr3d.PushBackNumber(0); tr3d.PushBackNumber(-27.5); tr3d.PushBackNumber(0);

	}

	// Create annotation appearance stream, a thumbnail which is used during printing or
	// in PDF processors that do not understand 3D data.
	Obj ap_dict = link_3D.PutDict("AP");
	{
		ElementBuilder builder;
		ElementWriter writer;
		writer.Begin(doc);

		std::string thumb_pathname(input_path + "dice.jpg");
		Image image = Image::Create(doc, thumb_pathname.c_str());
		writer.WritePlacedElement(builder.CreateImage(image, 0.0, 0.0, link_3D_rect.Width(), link_3D_rect.Height()));

		Obj normal_ap_stream = writer.End();
		normal_ap_stream.PutName("Subtype", "Form");
		normal_ap_stream.PutRect("BBox", 0, 0, link_3D_rect.Width(), link_3D_rect.Height());
		ap_dict.Put("N", normal_ap_stream);
	}
}

int main(int argc, char *argv[])
{
	int ret = 0;
	PDFNet::Initialize(LicenseKey);

	string output_path = "../../TestFiles/Output/";

	try  
	{	 
		PDFDoc doc;
		Page page = doc.PageCreate();
		doc.PagePushBack(page);
		Obj annots = doc.CreateIndirectArray();
		page.GetSDFObj().Put("Annots", annots);

		Create3DAnnotation(doc, annots);
		doc.Save((output_path + "dice_u3d.pdf").c_str(), SDFDoc::e_linearized, 0);
		cout << "Done" << endl;
	}
	catch(Common::Exception& e)
	{
		cout << e << endl;
		ret = 1;
	}
	catch(...)
	{
		cout << "Unknown Exception" << endl;
		ret = 1;
	}

	PDFNet::Terminate();
	return ret;
}
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2021 by PDFTron Systems Inc. All Rights Reserved.
// Consult LICENSE.txt regarding license information.
//---------------------------------------------------------------------------------------

package main
import (
	"fmt"
	. "pdftron"
)

import  "pdftron/Samples/LicenseKey/GO"

// Relative path to the folder containing the test files.
var inputPath = "../../TestFiles/"
var outputPath = "../../TestFiles/Output/"

func Create3DAnnotation(doc PDFDoc, annots Obj){
    // ---------------------------------------------------------------------------------
    // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
    // for collections of three-dimensional objects, such as those used by CAD software, 
    // to be embedded in PDF files.
    link3D := doc.CreateIndirectDict()
    link3D.PutName("Subtype", "3D")
    
    // Annotation location on the page
    link3DRect := NewRect(25.0, 180.0, 585.0, 643.0)
    link3D.PutRect("Rect", link3DRect.GetX1(), link3DRect.GetY1(),
                    link3DRect.GetX2(), link3DRect.GetY2())
    annots.PushBack(link3D)
    
    // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
    // that determines how the state of the annotation and its associated artwork can change.
    activationDict3D := link3D.PutDict("3DA")
    
    // Set the annotation so that it is activated as soon as the page containing the 
    // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
    activationDict3D.PutName("A", "PO")  
    
    // Embed U3D Streams (3D Model/Artwork).
    u3dFile := NewMappedFile(inputPath + "dice.u3d")
    u3dReader := NewFilterReader(u3dFile)
    u3dDataDict := doc.CreateIndirectStream(u3dReader, NewFilter())
    u3dDataDict.PutName("Subtype", "U3D")
    link3D.Put("3DD", u3dDataDict)
    
    // Set the initial view of the 3D artwork that should be used when the annotation is activated.
    view3DDict := link3D.PutDict("3DV")
    
    view3DDict.PutString("IN", "Unnamed")
    view3DDict.PutString("XN", "Default")
    view3DDict.PutName("MS", "M")
    view3DDict.PutNumber("CO", 27.5)
    
    // A 12-element 3D transformation matrix that specifies a position and orientation 
    // of the camera in world coordinates.
    tr3d := view3DDict.PutArray("C2W")
    tr3d.PushBackNumber(1.0)
    tr3d.PushBackNumber(0.0)
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(-1.0)
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(1.0) 
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(0.0) 
    tr3d.PushBackNumber(-27.5) 
    tr3d.PushBackNumber(0.0)
    
    // Create annotation appearance stream, a thumbnail which is used during printing or
    // in PDF processors that do not understand 3D data.
    apDict := link3D.PutDict("AP")
    
    builder := NewElementBuilder()
    writer := NewElementWriter()
    writer.Begin(doc.GetSDFDoc())
    
    thumbPathname := inputPath + "dice.jpg"
    image := ImageCreate(doc.GetSDFDoc(), thumbPathname)
    writer.WritePlacedElement(builder.CreateImage(image, 0.0, 0.0, float64(link3DRect.Width()), float64(link3DRect.Height())))
    
    normalApStream := writer.End()
    normalApStream.PutName("Subtype", "Form")
    normalApStream.PutRect("BBox", 0.0, 0.0, float64(link3DRect.Width()), float64(link3DRect.Height()))
    apDict.Put("N", normalApStream)
}

func main(){
    PDFNetInitialize(PDFTronLicense.Key)
    
    doc := NewPDFDoc()
    page := doc.PageCreate()
    doc.PagePushBack(page)
    annots := doc.CreateIndirectArray()
    page.GetSDFObj().Put("Annots", annots)
    
    Create3DAnnotation(doc, annots)
    doc.Save(outputPath + "dice_u3d.pdf", uint(SDFDocE_linearized))
    doc.Close()
    PDFNetTerminate()
    fmt.Println("Done.")
}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

import com.pdftron.pdf.*;
import com.pdftron.sdf.Obj;
import com.pdftron.sdf.SDFDoc;
import com.pdftron.common.PDFNetException;
import com.pdftron.filters.*;


public class U3DTest {

    static String input_path = "../../TestFiles/";

    static void Create3DAnnotation(PDFDoc doc, Obj annots) throws PDFNetException {
        // ---------------------------------------------------------------------------------
        // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability
        // for collections of three-dimensional objects, such as those used by CAD software,
        // to be embedded in PDF files.
        Obj link_3D = doc.createIndirectDict();
        link_3D.putName("Subtype", "3D");

        // Annotation location on the page
        Rect link_3D_rect = new Rect(25, 180, 585, 643);
        link_3D.putRect("Rect", link_3D_rect.getX1(), link_3D_rect.getY1(),
                link_3D_rect.getX2(), link_3D_rect.getY2());
        annots.pushBack(link_3D);

        // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual)
        // that determines how the state of the annotation and its associated artwork can change.
        Obj activation_dict_3D = link_3D.putDict("3DA");

        // Set the annotation so that it is activated as soon as the page containing the
        // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
        activation_dict_3D.putName("A", "PO");

        // Embed U3D Streams (3D Model/Artwork).
        {
            MappedFile u3d_file = new MappedFile(input_path + "dice.u3d");
            FilterReader u3d_reader = new FilterReader(u3d_file);

            // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
            Obj u3d_data_dict = doc.createIndirectStream(u3d_reader, new FlateEncode(null));
            u3d_data_dict.putName("Subtype", "U3D");
            link_3D.put("3DD", u3d_data_dict);
        }

        // Set the initial view of the 3D artwork that should be used when the annotation is activated.
        Obj view3D_dict = link_3D.putDict("3DV");
        {
            view3D_dict.putString("IN", "Unnamed");
            view3D_dict.putString("XN", "Default");
            view3D_dict.putName("MS", "M");
            view3D_dict.putNumber("CO", 27.5);

            // A 12-element 3D transformation matrix that specifies a position and orientation
            // of the camera in world coordinates.
            Obj tr3d = view3D_dict.putArray("C2W");
            tr3d.pushBackNumber(1);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(-1);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(1);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(0);
            tr3d.pushBackNumber(-27.5);
            tr3d.pushBackNumber(0);

        }

        // Create annotation appearance stream, a thumbnail which is used during printing or
        // in PDF processors that do not understand 3D data.
        Obj ap_dict = link_3D.putDict("AP");
        {
            ElementBuilder builder = new ElementBuilder();
            ElementWriter writer = new ElementWriter();
            writer.begin(doc);

            String thumb_pathname = input_path + "dice.jpg";
            Image image = Image.create(doc, thumb_pathname);
            writer.writePlacedElement(builder.createImage(image, 0.0, 0.0, link_3D_rect.getWidth(), link_3D_rect.getHeight()));

            Obj normal_ap_stream = writer.end();
            normal_ap_stream.putName("Subtype", "Form");
            normal_ap_stream.putRect("BBox", 0, 0, link_3D_rect.getWidth(), link_3D_rect.getHeight());
            ap_dict.put("N", normal_ap_stream);
        }
    }

    public static void main(String[] args) {
        String output_path = "../../TestFiles/Output/";
        PDFNet.initialize(PDFTronLicense.Key());
        try (PDFDoc doc = new PDFDoc()) {
            Page page = doc.pageCreate();
            doc.pagePushBack(page);
            Obj annots = doc.createIndirectArray();
            page.getSDFObj().put("Annots", annots);

            Create3DAnnotation(doc, annots);
            doc.save(output_path + "dice_u3d.pdf", SDFDoc.SaveMode.LINEARIZED, null);
            System.out.println("Done");
        } catch (Exception e) {
            e.printStackTrace();
        }

        PDFNet.terminate();
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

const { PDFNet } = require('@pdftron/pdfnet-node');
const PDFTronLicense = require('../LicenseKey/LicenseKey');

((exports) => {
  'use strict';

  exports.runU3DTest = () => {
    const input_path = '../TestFiles/';

    const create3DAnnotation = async (doc, annots) => {
      // ---------------------------------------------------------------------------------
      // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
      // for collections of three-dimensional objects, such as those used by CAD software, 
      // to be embedded in PDF files.
      const link_3D = await doc.createIndirectDict();
      link_3D.putName('Subtype', '3D');

      // Annotation location on the page
      const link_3D_rect = await PDFNet.Rect.init(25, 180, 585, 643);
      link_3D.putRect('Rect', link_3D_rect.x1, link_3D_rect.y1,
        link_3D_rect.x2, link_3D_rect.y2);
      annots.pushBack(link_3D);

      // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
      // that determines how the state of the annotation and its associated artwork can change.
      const activation_dict_3D = await link_3D.putDict('3DA');

      // Set the annotation so that it is activated as soon as the page containing the 
      // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
      activation_dict_3D.putName('A', 'PO');

      // Embed U3D Streams (3D Model/Artwork).
      const u3d_file = await PDFNet.Filter.createMappedFileFromUString(input_path + 'dice.u3d');
      const u3d_reader = await PDFNet.FilterReader.create(u3d_file);

      // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
      const flateEncode = await PDFNet.Filter.createFlateEncode();
      const u3d_data_dict = await doc.createIndirectStreamFromFilter(u3d_reader, flateEncode);
      u3d_data_dict.putName('Subtype', 'U3D');
      link_3D.put('3DD', u3d_data_dict);

      // Set the initial view of the 3D artwork that should be used when the annotation is activated.
      const view3D_dict = await link_3D.putDict('3DV');
      view3D_dict.putString('IN', 'Unnamed');
      view3D_dict.putString('XN', 'Default');
      view3D_dict.putName('MS', 'M');
      view3D_dict.putNumber('CO', 27.5);

      // A 12-element 3D transformation matrix that specifies a position and orientation 
      // of the camera in world coordinates.
      const tr3d = await view3D_dict.putArray('C2W');
      tr3d.pushBackNumber(1); tr3d.pushBackNumber(0); tr3d.pushBackNumber(0);
      tr3d.pushBackNumber(0); tr3d.pushBackNumber(0); tr3d.pushBackNumber(-1);
      tr3d.pushBackNumber(0); tr3d.pushBackNumber(1); tr3d.pushBackNumber(0);
      tr3d.pushBackNumber(0); tr3d.pushBackNumber(-27.5); tr3d.pushBackNumber(0);

      // Create annotation appearance stream, a thumbnail which is used during printing or
      // in PDF processors that do not understand 3D data.
      const ap_dict = await link_3D.putDict('AP');

      const builder = await PDFNet.ElementBuilder.create();
      const writer = await PDFNet.ElementWriter.create();

      writer.begin(doc);

      const thumb_pathname = input_path + 'dice.jpg';
      const image = await PDFNet.Image.createFromFile(doc, thumb_pathname);
      writer.writePlacedElement(await builder.createImageScaled(image, 0.0, 0.0, await link_3D_rect.width(), await link_3D_rect.height()));

      const normal_ap_stream = await writer.end();
      normal_ap_stream.putName('Subtype', 'Form');
      normal_ap_stream.putRect('BBox', 0, 0, await link_3D_rect.width(), await link_3D_rect.height());
      ap_dict.put('N', normal_ap_stream);
    }

    const main = async () => {
      const output_path = '../TestFiles/Output/';

      try {
        const doc = await PDFNet.PDFDoc.create();
        const page = await doc.pageCreate();
        doc.pagePushBack(page);
        const annots = await doc.createIndirectArray();
        page.getSDFObj().then(sdf => sdf.put('Annots', annots));

        await create3DAnnotation(doc, annots);
        doc.save(output_path + 'dice_u3d.pdf', PDFNet.SDFDoc.SaveOptions.e_linearized);
        console.log('Done');
      } catch (err) {
        console.log(err);
      }
    }
    PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error) {
      console.log('Error: ' + JSON.stringify(error));
    }).then(function(){ return PDFNet.shutdown(); });
  };
  exports.runU3DTest();
})(exports);
// eslint-disable-next-line spaced-comment
//# sourceURL=U3DTest.js
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

import site
site.addsitedir("../../../PDFNetC/Lib")
import sys
from PDFNetPython import *

sys.path.append("../../LicenseKey/PYTHON")
from LicenseKey import *

# Relative path to the folder containing the test files.
input_path = "../../TestFiles/"
output_path = "../../TestFiles/Output/"

def Create3DAnnotation(doc, annots):
    # ---------------------------------------------------------------------------------
    # Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
    # for collections of three-dimensional objects, such as those used by CAD software, 
    # to be embedded in PDF files.
    link_3D = doc.CreateIndirectDict()
    link_3D.PutName("Subtype", "3D")
    
    # Annotation location on the page
    link_3D_rect = Rect(25, 180, 585, 643)
    link_3D.PutRect("Rect", link_3D_rect.x1, link_3D_rect.y1,
                    link_3D_rect.x2, link_3D_rect.y2)
    annots.PushBack(link_3D)
    
    # The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
    # that determines how the state of the annotation and its associated artwork can change.
    activation_dict_3D = link_3D.PutDict("3DA")
    
    # Set the annotation so that it is activated as soon as the page containing the 
    # annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
    activation_dict_3D.PutName("A", "PO")  
    
    # Embed U3D Streams (3D Model/Artwork).
    u3d_file = MappedFile(input_path + "dice.u3d")
    u3d_reader = FilterReader(u3d_file)
    
    u3d_data_dict = doc.CreateIndirectStream(u3d_reader, FlateEncode(Filter()))
    u3d_data_dict.PutName("Subtype", "U3D")
    link_3D.Put("3DD", u3d_data_dict)
    
    # Set the initial view of the 3D artwork that should be used when the annotation is activated.
    view3D_dict = link_3D.PutDict("3DV")
    
    view3D_dict.PutString("IN", "Unnamed")
    view3D_dict.PutString("XN", "Default")
    view3D_dict.PutName("MS", "M")
    view3D_dict.PutNumber("CO", 27.5)
    
    # A 12-element 3D transformation matrix that specifies a position and orientation 
    # of the camera in world coordinates.
    tr3d = view3D_dict.PutArray("C2W")
    tr3d.PushBackNumber(1)
    tr3d.PushBackNumber(0)
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(-1)
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(1) 
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(0) 
    tr3d.PushBackNumber(-27.5) 
    tr3d.PushBackNumber(0)
    
    # Create annotation appearance stream, a thumbnail which is used during printing or
    # in PDF processors that do not understand 3D data.
    ap_dict = link_3D.PutDict("AP")
    
    builder = ElementBuilder()
    writer = ElementWriter()
    writer.Begin(doc.GetSDFDoc())
    
    thumb_pathname = input_path + "dice.jpg"
    image = Image.Create(doc.GetSDFDoc(), thumb_pathname)
    writer.WritePlacedElement(builder.CreateImage(image, 0.0, 0.0, link_3D_rect.Width(), link_3D_rect.Height()))
    
    normal_ap_stream = writer.End()
    normal_ap_stream.PutName("Subtype", "Form")
    normal_ap_stream.PutRect("BBox", 0, 0, link_3D_rect.Width(), link_3D_rect.Height())
    ap_dict.Put("N", normal_ap_stream)

def main():
    PDFNet.Initialize(LicenseKey)
    
    doc = PDFDoc()
    page = doc.PageCreate()
    doc.PagePushBack(page)
    annots = doc.CreateIndirectArray()
    page.GetSDFObj().Put("Annots", annots)
    
    Create3DAnnotation(doc, annots)
    doc.Save(output_path + "dice_u3d.pdf", SDFDoc.e_linearized)
    doc.Close()
    PDFNet.Terminate()
    print("Done.")

if __name__ == '__main__':
    main()
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
<?php
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
// Consult LICENSE.txt regarding license information.
//---------------------------------------------------------------------------------------
if(file_exists("../../../PDFNetC/Lib/PDFNetPHP.php"))
include("../../../PDFNetC/Lib/PDFNetPHP.php");
include("../../LicenseKey/PHP/LicenseKey.php");

// Relative path to the folder containing the test files.
$input_path = getcwd()."/../../TestFiles/";
$output_path = $input_path."Output/";

function Create3DAnnotation($doc, $annots)
{
	// ---------------------------------------------------------------------------------
	// Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
	// for collections of three-dimensional objects, such as those used by CAD software, 
	// to be embedded in PDF files.
	$link_3D = $doc->CreateIndirectDict();
	$link_3D->PutName("Subtype", "3D");

	// Annotation location on the page
	$link_3D_rect = new Rect(25.0, 180.0, 585.0, 643.0);
	$link_3D->PutRect("Rect", $link_3D_rect->x1, $link_3D_rect->y1,
		$link_3D_rect->x2, $link_3D_rect->y2);
	$annots->PushBack($link_3D);

	// The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
	// that determines how the state of the annotation and its associated artwork can change.
	$activation_dict_3D = $link_3D->PutDict("3DA");

	// Set the annotation so that it is activated as soon as the page containing the 
	// annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
	$activation_dict_3D->PutName("A", "PO");  

	// Embed U3D Streams (3D Model/Artwork).
	global $input_path;
	$u3d_file = new MappedFile($input_path."dice.u3d");
	$u3d_reader = new FilterReader($u3d_file);

	// To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
	$u3d_data_dict = $doc->CreateIndirectStream($u3d_reader, new FlateEncode(new Filter()));
	$u3d_data_dict->PutName("Subtype", "U3D");
	$link_3D->Put("3DD", $u3d_data_dict);

	// Set the initial view of the 3D artwork that should be used when the annotation is activated.
	$view3D_dict = $link_3D->PutDict("3DV");
	
	$view3D_dict->PutString("IN", "Unnamed");
	$view3D_dict->PutString("XN", "Default");
	$view3D_dict->PutName("MS", "M");
	$view3D_dict->PutNumber("CO", 27.5);

	// A 12-element 3D transformation matrix that specifies a position and orientation 
	// of the camera in world coordinates.
	$tr3d =	$view3D_dict->PutArray("C2W"); 
	$tr3d->PushBackNumber(1); $tr3d->PushBackNumber(0); $tr3d->PushBackNumber(0); 
	$tr3d->PushBackNumber(0); $tr3d->PushBackNumber(0); $tr3d->PushBackNumber(-1);
	$tr3d->PushBackNumber(0); $tr3d->PushBackNumber(1); $tr3d->PushBackNumber(0); 
	$tr3d->PushBackNumber(0); $tr3d->PushBackNumber(-27.5); $tr3d->PushBackNumber(0);

	// Create annotation appearance stream, a thumbnail which is used during printing or
	// in PDF processors that do not understand 3D data.
	$ap_dict = $link_3D->PutDict("AP");
	
	$builder = new ElementBuilder();
	$writer = new ElementWriter();
	$writer->Begin($doc->GetSDFDoc());

	$thumb_pathname = $input_path."dice.jpg";
	$image = Image::Create($doc->GetSDFDoc(), $thumb_pathname);
	$writer->WritePlacedElement($builder->CreateImage($image, 0.0, 0.0, $link_3D_rect->Width(), $link_3D_rect->Height()));

	$normal_ap_stream = $writer->End();
	$normal_ap_stream->PutName("Subtype", "Form");
	$normal_ap_stream->PutRect("BBox", 0, 0, $link_3D_rect->Width(), $link_3D_rect->Height());
	$ap_dict->Put("N", $normal_ap_stream);
}

// ---------------------------------------------------------------------------------

	PDFNet::Initialize($LicenseKey);
	PDFNet::GetSystemFontList();    // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.	

	$doc = new PDFDoc();
	$page = $doc->PageCreate();
	$doc->PagePushBack($page);
	$annots = $doc->CreateIndirectArray();
	$page->GetSDFObj()->Put("Annots", $annots);

	Create3DAnnotation($doc, $annots);
	$doc->Save($output_path."dice_u3d.pdf", SDFDoc::e_linearized);
	PDFNet::Terminate();
	echo "Done.\n";	
?>
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

require '../../../PDFNetC/Lib/PDFNetRuby'
include PDFNetRuby
require '../../LicenseKey/RUBY/LicenseKey'

$stdout.sync = true

# Relative path to the folder containing the test files.
$input_path = "../../TestFiles/"
$output_path = "../../TestFiles/Output/"

def Create3DAnnotation(doc, annots)
	# ---------------------------------------------------------------------------------
	# Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
	# for collections of three-dimensional objects, such as those used by CAD software, 
	# to be embedded in PDF files.
	link_3D = doc.CreateIndirectDict
	link_3D.PutName("Subtype", "3D")
	
	# Annotation location on the page
	link_3D_rect = Rect.new(25, 180, 585, 643)
	link_3D.PutRect("Rect", link_3D_rect.x1, link_3D_rect.y1,
			link_3D_rect.x2, link_3D_rect.y2)
	annots.PushBack(link_3D)
	
	# The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
	# that determines how the state of the annotation and its associated artwork can change.
	activation_dict_3D = link_3D.PutDict("3DA")
	
	# Set the annotation so that it is activated as soon as the page containing the 
	# annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
	activation_dict_3D.PutName("A", "PO")  
	
	# Embed U3D Streams (3D Model/Artwork).
	u3d_file = MappedFile.new($input_path + "dice.u3d")
	u3d_reader = FilterReader.new(u3d_file)
	
	u3d_data_dict = doc.CreateIndirectStream(u3d_reader, FlateEncode.new(Filter.new))
	u3d_data_dict.PutName("Subtype", "U3D")
	link_3D.Put("3DD", u3d_data_dict)
	
	# Set the initial view of the 3D artwork that should be used when the annotation is activated.
	view3D_dict = link_3D.PutDict("3DV")
	
	view3D_dict.PutString("IN", "Unnamed")
	view3D_dict.PutString("XN", "Default")
	view3D_dict.PutName("MS", "M")
	view3D_dict.PutNumber("CO", 27.5)
	
	# A 12-element 3D transformation matrix that specifies a position and orientation 
	# of the camera in world coordinates.
	tr3d = view3D_dict.PutArray("C2W")
	tr3d.PushBackNumber(1)
	tr3d.PushBackNumber(0)
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(-1)
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(1) 
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(0) 
	tr3d.PushBackNumber(-27.5) 
	tr3d.PushBackNumber(0)
	
	# Create annotation appearance stream, a thumbnail which is used during printing or
	# in PDF processors that do not understand 3D data.
	ap_dict = link_3D.PutDict("AP")
	
	builder = ElementBuilder.new
	writer = ElementWriter.new
	writer.Begin(doc.GetSDFDoc)
	
	thumb_pathname = $input_path + "dice.jpg"
	image = Image.Create(doc.GetSDFDoc, thumb_pathname)
	writer.WritePlacedElement(builder.CreateImage(image, 0.0, 0.0, link_3D_rect.Width, link_3D_rect.Height))
	
	normal_ap_stream = writer.End
	normal_ap_stream.PutName("Subtype", "Form")
	normal_ap_stream.PutRect("BBox", 0, 0, link_3D_rect.Width, link_3D_rect.Height)
	ap_dict.Put("N", normal_ap_stream)
end

	PDFNet.Initialize(PDFTronLicense.Key)
	
	doc = PDFDoc.new
	page = doc.PageCreate
	doc.PagePushBack(page)
	annots = doc.CreateIndirectArray
	page.GetSDFObj.Put("Annots", annots)
	
	Create3DAnnotation(doc, annots)
	doc.Save($output_path + "dice_u3d.pdf", SDFDoc::E_linearized)
	doc.Close
	PDFNet.Terminate
	puts "Done."
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
'
' Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
'
Imports System
Imports pdftron 
Imports pdftron.Common 
Imports pdftron.Filters 
Imports pdftron.SDF 
Imports PDFTRON.PDF
Module U3DTestVB
    Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

    Sub Main()
        PDFNet.Initialize(PDFTronLicense.Key)
        Const output_path As String = "../../../../TestFiles/Output/"

        Try
			Using doc As PDFDoc = New PDFDoc
				Dim page As Page = doc.PageCreate
				doc.PagePushBack(page)
				Dim annots As Obj = doc.CreateIndirectArray
				page.GetSDFObj.Put("Annots", annots)
				U3DTest.Create3DAnnotation(doc, annots)
				doc.Save(output_path + "dice_u3d.pdf", SDFDoc.SaveOptions.e_linearized)
				Console.WriteLine("Done. Result saved in dice_u3d.pdf")
			End Using
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try
        PDFNet.Terminate()
    End Sub

    Class U3DTest
        Shared Sub Create3DAnnotation(ByVal doc As PDFDoc, ByVal annots As Obj)
            ' ---------------------------------------------------------------------------------
            ' Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability 
            ' for collections of three-dimensional objects, such as those used by CAD software, 
            ' to be embedded in PDF files.

            Const input_path As String = "../../../../TestFiles/"
            Dim link_3D As Obj = doc.CreateIndirectDict
            link_3D.PutName("Subtype", "3D")

            ' Annotation location on the page
            Dim bbox As Rect = New Rect(25, 180, 585, 643)
            link_3D.PutRect("Rect", bbox.x1, bbox.y1, bbox.x2, bbox.y2)
            annots.PushBack(link_3D)

            ' The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual) 
            ' that determines how the state of the annotation and its associated artwork can change.
            Dim activation_dict_3D As Obj = link_3D.PutDict("3DA")

            ' Set the annotation so that it is activated as soon as the page containing the 
            ' annotation is opened. Other options are: PV (page view) and XA (explicit) activation.

            ' Embed U3D Streams (3D Model/Artwork).
            activation_dict_3D.PutName("A", "PO")
            Dim u3d_file As MappedFile = New MappedFile(input_path + "dice.u3d")
            Dim u3d_reader As FilterReader = New FilterReader(u3d_file)
            Dim u3d_data_dict As Obj = doc.CreateIndirectStream(u3d_reader)
            u3d_data_dict.PutName("Subtype", "U3D")
            link_3D.Put("3DD", u3d_data_dict)

            ' Set the initial view of the 3D artwork that should be used when the annotation is activated.
            Dim view3D_dict As Obj = link_3D.PutDict("3DV")
            view3D_dict.PutString("IN", "Unnamed")
            view3D_dict.PutString("XN", "Default")
            view3D_dict.PutName("MS", "M")
            view3D_dict.PutNumber("CO", 27.5)

            ' A 12-element 3D transformation matrix that specifies a position and orientation 
            ' of the camera in world coordinates.
            Dim tr3d As Obj = view3D_dict.PutArray("C2W")
            tr3d.PushBackNumber(1)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(-1)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(1)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(0)
            tr3d.PushBackNumber(-27.5)
            tr3d.PushBackNumber(0)

            ' Create annotation appearance stream, a thumbnail which is used during printing or
            ' in PDF processors that do not understand 3D data.
            Dim ap_dict As Obj = link_3D.PutDict("AP")

			Using builder As ElementBuilder = New ElementBuilder
				Using writer As ElementWriter = New ElementWriter
					writer.Begin(doc.GetSDFDoc)
					writer.WritePlacedElement(builder.CreateImage(Image.Create(doc.GetSDFDoc, input_path + "dice.jpg"), 0, 0, bbox.Width, bbox.Height))
					Dim normal_ap_stream As Obj = writer.End
					normal_ap_stream.PutName("Subtype", "Form")
					normal_ap_stream.PutRect("BBox", 0, 0, bbox.Width, bbox.Height)
					ap_dict.Put("N", normal_ap_stream)
				End Using
			End Using
		End Sub
    End Class

End Module
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/get-started/samples/u3dtest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
