Creating U3D annotations.

Q: I am trying to embed an U3D models in a PDF annotation. I have
successfully embedded an U3D model to an existing 3d annotation, but
is seems to override the one that was already there. And it seems to
override the annotation’s javascript as well.

I have been using your library to attatch the U3D models. Is embedding
multiple U3D files possible with the current library distribution? I
have attatched the code I am using so far as an example:

static void AnnotationHighLevelAPI(PDFDoc doc) throws PDFNetException
{
System.out.println("Traversing all annotations in the document...");
int page_num = 1;
for (PageIterator itr = doc.getPageIterator(); itr.hasNext():wink: {
  System.out.println("Page " + (page_num++) + ": ");

  Page page = (Page) (itr.next());
  int num_annots = page.getNumAnnots();
  for (int i = 0; i < num_annots; ++i) {
    Annot annot = page.getAnnot(i);
    if (annot.isValid() == false) continue;
    System.out.println("Annot Type: " +
annot.getSDFObj().get("Subtype").value().getName());

    double[] bbox = annot.getRect().get();
    System.out.println(" Position: " + ", " + bbox[0] + ", "
        + bbox[1] + ", " + bbox[2] + ", " + bbox[3]);

    // my annotation is on the right side of the screen
    if (bbox[0] > 140) {
      Obj cosAnnot = annot.getSDFObj();
      StdFile u3d_file = new StdFile(("c:/model.u3d"),
StdFile.e_read_mode);
      FilterReader u3d_reader = new FilterReader(u3d_file);
      Obj u3d_data_dict = doc.createIndirectStream(u3d_reader,new
FlateEncode(null));
      u3d_data_dict.putName("Subtype", "U3D");
      cosAnnot.put("3DD", u3d_data_dict);
    }
  }
  }
}

public static void main(String[] args) {
PDFNet.initialize();
try {
  PDFDoc doc = new PDFDoc(("c:/myPdf.pdf"));
  doc.initSecurityHandler();
  AnnotationHighLevelAPI(doc);
  doc.save(("c:/test.pdf"), SDFDoc.e_incremental, null);
} catch (Exception e) {
  e.printStackTrace();
}

PDFNet.terminate();
}
---------------
A: Based on your sample code you are currently modifying (editing)
existing annotations on the page. So you are overwriting existing
annotations and converting them to U3D annotations.

In case you would simply like to add a new 3D annotation to a page,
please take a look at U3D sample project (http://www.pdftron.com/net/
samplecode.html#U3D). You can further extend Create3DAnnotation()
method to pass in the positioning and other information.

Q: To clarify: I am not trying to add a new annotation to the
document, I am trying to Add models to an existing 3D annotation so
that I can load them using javascript like the example on the
following page: http://www.theorie3.de/Downloads/PDF%20Beispiele/BoxoBalls.pdf
-----
A: We looked into the file and you should be able to recreate
everything in that file using PDFNet.

As a starting point, download and install CosEdit (www.pdftron.com/
cosedit). This is a small utility that will help you to inspect
contents of the original PDF, so that you can use PDFNet SDK API to
recreate similar structures.

In CosEdit, open BoxoBalls1.pdf and paste the following line in the
address bar:

'trailer/Root/Pages/Kids/0/Annots/0/'

This will show all entries in the 3D annotation dictionary.

There are a number of entries that may be of interest, but it seems
that additional 3D models and other resources are stored under: 3DD/
Resources/Names

The full path is: trailer/Root/Pages/Kids/0/Annots/0/3DD/Resources/
Names

Using SDF/Cos API (http://www.pdftron.com/net/samplecode/SDFTest.cs)
in PDFNet you can recreate all of these structures.

Q: Thanks again for your time, I have good news, I have been able to
load The attached resource.

PDF documentation suggests a stream link should containd a key
'Filter' and a value 'FlateDecode' (mandatory) but this is not the
case. When I remove this key and it's value, it works fine

Thanks again for the excellent support.
-----
A: 'Filter' key is used to indicate that the data stream is compressed
using a given compression method. If the stream is not compressed
setting 'Filter' key will result in a corrupt document.

Using PDFNet you can create Flate encoded stream as follows:

Obj stm = doc.CreateIndirectStream(mystm, new FlateEncode(null));

For relevant code you may want to take a look at SDFTest sample
project (http://www.pdftron.com/net/samplecode.html#SDF).

Please note that CreateIndirectStream() will automatically set the
'Filter' key in the stream dictionary for you.

Thanks for the tip. I overlooked the second parameter for the
CreateIndirectStream method. I added the encoding wich results in a
smaller file size (wich nice because I am attaching a lot of
resources).

Thanks again.

Q: Attaching a file works fine now, but I have an other challenge.

I have 4 files, if I attach the files to the annotation in the
following order 1,2,3,4 I get the following error when I try to load
element 4

Line: 15: Code: 31(0x1f): Bad or invalid URI: Resource
Line: 16: Code: 45(0x2d): Object is invalid

But when I attach them in the following order:
4,3,2,1 I get an error when I try to load element 1 (not always in
this order)

(all individual files work fine when they are the only file I attach
to the annotation.)

I have attached my class that attaches the files, maybe I am
forgetting something…

public class PDFAttach {
      public void attach(String sourceFile, String destinationFile,
int annotation, ArrayList<File> attachments) {
            PDFNet.initialize();
            try {

                  PDFDoc doc = new PDFDoc((sourceFile));
                  doc.initSecurityHandler();

                  Obj pdfObject = doc.getPage(1).getAnnots();
                  pdfObject =
pdfObject.getAt(annotation).find("3DD").value();

                  attachFileToPDF(doc, pdfObject, attachments);

                  doc.save((destinationFile), 0, null, "%PDF-1.7");

            } catch (Exception e) {
                  e.printStackTrace();
            }
            PDFNet.terminate();
      }

      private static void attachFileToPDF(SDFDoc doc, Obj cosOBJ,
ArrayList<File> filesToAdd) {
            try {
                  Obj custom_dict = doc.createIndirectDict();
                  Obj custom_array = custom_dict.putArray("Names");
                  for (int i = 0; i < filesToAdd.size(); i++) {

System.out.println(filesToAdd.get(i).getName());

custom_array.pushBackString(filesToAdd.get(i).getName());

                        StdFile embed_file = new
StdFile(filesToAdd.get(i).getAbsolutePath(), StdFile.e_read_mode);
                        FilterReader mystm = new
FilterReader(embed_file);

                        Obj embeddedFile =
doc.createIndirectStream(mystm, new FlateEncode(null));
                        embeddedFile.putName("Subtype", "U3D");
                        custom_array.pushBack(embeddedFile);
                  }
                  cosOBJ.put("Resources", custom_dict);
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }
}
------
A: Solved the problem, it is REAL strange and it took me some time to
figure it out, but attaching file’s with a name that ends in 2 numbers
e.g. item10.u3d or item11.u3d results in an error. When I rename these
files to itemA.u3d / itemB.u3d everything works fine.

I would like to thank you once again for your reply’s / tips.