U3D

Sample Obj-C code for using Apryse SDK to embed U3D content (3 dimensional models) in PDF files. Learn more about our iOS SDK.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6#import <OBJC/PDFNetOBJC.h>
7#import <Foundation/Foundation.h>
8
9void Create3DAnnotation(PTPDFDoc* doc, PTObj* annots)
10{
11 // ---------------------------------------------------------------------------------
12 // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability
13 // for collections of three-dimensional objects, such as those used by CAD software,
14 // to be embedded in PDF files.
15 PTObj * link_3D = [doc CreateIndirectDict];
16 [link_3D PutName: @"Subtype" name: @"3D"];
17
18 // Annotation location on the page
19 PTPDFRect * link_3D_rect = [[PTPDFRect alloc] init];
20 [link_3D_rect Set: 25 y1: 180 x2: 585 y2: 643];
21 [link_3D PutRect: @"Rect" x1: [link_3D_rect GetX1] y1: [link_3D_rect GetY1] x2: [link_3D_rect GetX2] y2: [link_3D_rect GetY2]];
22 [annots PushBack: link_3D];
23
24 // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual)
25 // that determines how the state of the annotation and its associated artwork can change.
26 PTObj * activation_dict_3D = [link_3D PutDict: @"3DA"];
27
28 // Set the annotation so that it is activated as soon as the page containing the
29 // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
30 [activation_dict_3D PutName: @"A" name: @"PO"];
31
32 // Embed U3D Streams (3D Model/Artwork).
33 {
34 PTMappedFile *u3d_file = [[PTMappedFile alloc] initWithFilename: @"../../TestFiles/dice.u3d"];
35 PTFilterReader *u3d_reader = [[PTFilterReader alloc] initWithFilter: u3d_file];
36
37 // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
38 PTFilter *f = [[PTFilter alloc] init];
39 PTObj * u3d_data_dict = [doc CreateIndirectStream: u3d_reader filter_chain: [[PTFlateEncode alloc] initWithInput_filter: [[PTFilter alloc] init] compression_level: -1 buf_sz: 256]];
40 [u3d_data_dict PutName: @"Subtype" name: @"U3D"];
41 [link_3D Put: @"3DD" obj: u3d_data_dict];
42 }
43
44 // Set the initial view of the 3D artwork that should be used when the annotation is activated.
45 PTObj * view3D_dict = [link_3D PutDict: @"3DV"];
46 {
47 [view3D_dict PutString: @"IN" value: @"Unnamed"];
48 [view3D_dict PutString: @"XN" value: @"Default"];
49 [view3D_dict PutName: @"MS" name: @"M"];
50 [view3D_dict PutNumber: @"CO" value: 27.5];
51
52 // A 12-element 3D transformation matrix that specifies a position and orientation
53 // of the camera in world coordinates.
54 PTObj * tr3d = [view3D_dict PutArray: @"C2W"];
55 [tr3d PushBackNumber: 1]; [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 0];
56 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: -1];
57 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 1]; [tr3d PushBackNumber: 0];
58 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: -27.5]; [tr3d PushBackNumber: 0];
59
60 }
61
62 // Create annotation appearance stream, a thumbnail which is used during printing or
63 // in PDF processors that do not understand 3D data.
64 PTObj * ap_dict = [link_3D PutDict: @"AP"];
65 {
66 PTElementBuilder *builder = [[PTElementBuilder alloc] init];
67 PTElementWriter *writer = [[PTElementWriter alloc] init];
68 [writer WriterBeginWithSDFDoc: [doc GetSDFDoc] compress: true];
69
70 NSString *thumb_pathname = @"../../TestFiles/dice.jpg";
71 PTImage *image = [PTImage CreateWithFile: [doc GetSDFDoc] filename: thumb_pathname encoder_hints: [[PTObj alloc] init]];
72 [writer WritePlacedElement: [builder CreateImageWithCornerAndScale: image x: 0.0 y: 0.0 hscale: [link_3D_rect Width] vscale: [link_3D_rect Height]]];
73
74 PTObj * normal_ap_stream = [writer End];
75 [normal_ap_stream PutName: @"Subtype" name: @"Form"];
76 [normal_ap_stream PutRect: @"BBox" x1: 0 y1: 0 x2: [link_3D_rect Width] y2: [link_3D_rect Height]];
77 [ap_dict Put: @"N" obj: normal_ap_stream];
78 }
79}
80
81int main(int argc, char *argv[])
82{
83 @autoreleasepool {
84 int ret = 0;
85 [PTPDFNet Initialize: 0];
86
87 @try
88 {
89 PTPDFDoc *doc = [[PTPDFDoc alloc] init];
90 PTPDFRect * rect = [[PTPDFRect alloc] init];
91 [rect Set: 0 y1: 0 x2: 612 y2: 792];
92 PTPage *page = [doc PageCreate: rect];
93 [doc PagePushBack: page];
94 PTObj * annots = [doc CreateIndirectArray];
95 [[page GetSDFObj] Put: @"Annots" obj: annots];
96
97 Create3DAnnotation(doc, annots);
98 [doc SaveToFile: @"../../TestFiles/Output/dice_u3d.pdf" flags: e_ptlinearized];
99 NSLog(@"Done");
100 }
101 @catch(NSException *e)
102 {
103 NSLog(@"%@", e.reason);
104 ret = 1;
105 }
106 [PTPDFNet Terminate: 0];
107 return ret;
108 }
109}

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 Obj-C | Apryse documentation