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