Some test text!

menu

Embed 3D models (U3D) in PDF files using Kotlin

More languages

chevron_right
More languages
Java (Android)
C++
C#
C# (.NET Core)
Go
Java
Kotlin
Obj-C
JS (Node.js)
PHP
Python
Ruby
Swift
C# (UWP)
VB
C# (Xamarin)

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

Get Started Samples Download

To run this sample, get started with a free trial of PDFTron SDK.

//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.android.pdfnetsdksamples.samples

import com.pdftron.android.pdfnetsdksamples.OutputListener
import com.pdftron.android.pdfnetsdksamples.PDFNetSample
import com.pdftron.android.pdfnetsdksamples.R
import com.pdftron.android.pdfnetsdksamples.util.Utils
import com.pdftron.common.PDFNetException
import com.pdftron.filters.FilterReader
import com.pdftron.filters.FlateEncode
import com.pdftron.filters.MappedFile
import com.pdftron.pdf.*
import com.pdftron.sdf.Obj
import com.pdftron.sdf.SDFDoc
import java.util.*

class U3DTest : PDFNetSample() {
    init {
        setTitle(R.string.sample_u3d_title)
        setDescription(R.string.sample_u3d_description)
    }

    override fun run(outputListener: OutputListener?) {
        super.run(outputListener)
        mOutputListener = outputListener
        mFileList.clear()
        printHeader(outputListener!!)
        try {

            val doc = PDFDoc()
            val page = doc.pageCreate()
            doc.pagePushBack(page)
            val annots = doc.createIndirectArray()
            page.sdfObj.put("Annots", annots)

            Create3DAnnotation(doc, annots)
            doc.save(Utils.createExternalFile("dice_u3d.pdf", mFileList).absolutePath, SDFDoc.SaveMode.LINEARIZED, null)
            doc.close()
            mOutputListener!!.println("Done")
        } catch (e: Exception) {
            mOutputListener!!.printError(e.stackTrace)
        }

        for (file in mFileList) {
            addToFileList(file)
        }
        printFooter(outputListener)
    }

    companion object {

        private var mOutputListener: OutputListener? = null

        private val mFileList = ArrayList<String>()

        @Throws(PDFNetException::class)
        internal fun 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.
            val link_3D = doc.createIndirectDict()
            link_3D.putName("Subtype", "3D")

            // Annotation location on the page
            val link_3D_rect = 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.
            val 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).
            run {
                val u3d_file = MappedFile(Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "dice.u3d")!!.absolutePath)
                val u3d_reader = FilterReader(u3d_file)

                // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
                val u3d_data_dict = doc.createIndirectStream(u3d_reader, 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.
            val view3D_dict = link_3D.putDict("3DV")
            run {
                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.
                val tr3d = view3D_dict.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.
            val ap_dict = link_3D.putDict("AP")
            run {
                val builder = ElementBuilder()
                val writer = ElementWriter()
                writer.begin(doc)

                val thumb_pathname = Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "dice.jpg")!!.absolutePath
                val image = Image.create(doc, thumb_pathname)
                writer.writePlacedElement(builder.createImage(image, 0.0, 0.0, link_3D_rect.width, link_3D_rect.height))

                val normal_ap_stream = writer.end()
                normal_ap_stream.putName("Subtype", "Form")
                normal_ap_stream.putRect("BBox", 0.0, 0.0, link_3D_rect.width, link_3D_rect.height)
                ap_dict.put("N", normal_ap_stream)
            }
        }
    }

}
close

Free Trial

Get unlimited trial usage of PDFTron SDK to bring accurate, reliable, and fast document processing capabilities to any application or workflow.

Select a platform to get started with your free trial.

Unlimited usage. No email address required.