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