U3D

Sample Kotlin code for using Apryse SDK to embed U3D content (3 dimensional models) in PDF files. Learn more about our Android SDK.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample
10import com.pdftron.android.pdfnetsdksamples.R
11import com.pdftron.android.pdfnetsdksamples.util.Utils
12import com.pdftron.common.PDFNetException
13import com.pdftron.filters.FilterReader
14import com.pdftron.filters.FlateEncode
15import com.pdftron.filters.MappedFile
16import com.pdftron.pdf.*
17import com.pdftron.sdf.Obj
18import com.pdftron.sdf.SDFDoc
19import java.util.*
20
21class U3DTest : PDFNetSample() {
22 init {
23 setTitle(R.string.sample_u3d_title)
24 setDescription(R.string.sample_u3d_description)
25 }
26
27 override fun run(outputListener: OutputListener?) {
28 super.run(outputListener)
29 mOutputListener = outputListener
30 mFileList.clear()
31 printHeader(outputListener!!)
32 try {
33
34 PDFDoc().use { doc ->
35 val page = doc.pageCreate()
36 doc.pagePushBack(page)
37 val annots = doc.createIndirectArray()
38 page.sdfObj.put("Annots", annots)
39
40 Create3DAnnotation(doc, annots)
41 doc.save(Utils.createExternalFile("dice_u3d.pdf", mFileList).absolutePath, SDFDoc.SaveMode.LINEARIZED, null)
42 mOutputListener!!.println("Done")
43 }
44 } catch (e: Exception) {
45 mOutputListener!!.printError(e.stackTrace)
46 }
47
48 for (file in mFileList) {
49 addToFileList(file)
50 }
51 printFooter(outputListener)
52 }
53
54 companion object {
55
56 private var mOutputListener: OutputListener? = null
57
58 private val mFileList = ArrayList<String>()
59
60 @Throws(PDFNetException::class)
61 internal fun Create3DAnnotation(doc: PDFDoc, annots: Obj) {
62 // ---------------------------------------------------------------------------------
63 // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability
64 // for collections of three-dimensional objects, such as those used by CAD software,
65 // to be embedded in PDF files.
66 val link_3D = doc.createIndirectDict()
67 link_3D.putName("Subtype", "3D")
68
69 // Annotation location on the page
70 val link_3D_rect = Rect(25.0, 180.0, 585.0, 643.0)
71 link_3D.putRect("Rect", link_3D_rect.x1, link_3D_rect.y1,
72 link_3D_rect.x2, link_3D_rect.y2)
73 annots.pushBack(link_3D)
74
75 // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual)
76 // that determines how the state of the annotation and its associated artwork can change.
77 val activation_dict_3D = link_3D.putDict("3DA")
78
79 // Set the annotation so that it is activated as soon as the page containing the
80 // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
81 activation_dict_3D.putName("A", "PO")
82
83 // Embed U3D Streams (3D Model/Artwork).
84 run {
85 val u3d_file = MappedFile(Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "dice.u3d")!!.absolutePath)
86 val u3d_reader = FilterReader(u3d_file)
87
88 // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
89 val u3d_data_dict = doc.createIndirectStream(u3d_reader, FlateEncode(null))
90 u3d_data_dict.putName("Subtype", "U3D")
91 link_3D.put("3DD", u3d_data_dict)
92 }
93
94 // Set the initial view of the 3D artwork that should be used when the annotation is activated.
95 val view3D_dict = link_3D.putDict("3DV")
96 run {
97 view3D_dict.putString("IN", "Unnamed")
98 view3D_dict.putString("XN", "Default")
99 view3D_dict.putName("MS", "M")
100 view3D_dict.putNumber("CO", 27.5)
101
102 // A 12-element 3D transformation matrix that specifies a position and orientation
103 // of the camera in world coordinates.
104 val tr3d = view3D_dict.putArray("C2W")
105 tr3d.pushBackNumber(1.0)
106 tr3d.pushBackNumber(0.0)
107 tr3d.pushBackNumber(0.0)
108 tr3d.pushBackNumber(0.0)
109 tr3d.pushBackNumber(0.0)
110 tr3d.pushBackNumber(-1.0)
111 tr3d.pushBackNumber(0.0)
112 tr3d.pushBackNumber(1.0)
113 tr3d.pushBackNumber(0.0)
114 tr3d.pushBackNumber(0.0)
115 tr3d.pushBackNumber(-27.5)
116 tr3d.pushBackNumber(0.0)
117
118 }
119
120 // Create annotation appearance stream, a thumbnail which is used during printing or
121 // in PDF processors that do not understand 3D data.
122 val ap_dict = link_3D.putDict("AP")
123 run {
124 val builder = ElementBuilder()
125 val writer = ElementWriter()
126 writer.begin(doc)
127
128 val thumb_pathname = Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "dice.jpg")!!.absolutePath
129 val image = Image.create(doc, thumb_pathname)
130 writer.writePlacedElement(builder.createImage(image, 0.0, 0.0, link_3D_rect.width, link_3D_rect.height))
131
132 val normal_ap_stream = writer.end()
133 normal_ap_stream.putName("Subtype", "Form")
134 normal_ap_stream.putRect("BBox", 0.0, 0.0, link_3D_rect.width, link_3D_rect.height)
135 ap_dict.put("N", normal_ap_stream)
136 }
137 }
138 }
139
140}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales
Embed 3D Models (U3D) in PDF Using Kotlin | Apryse documentation