PDFlib Cookbook

cookbook

pdf_3D/javascript_for_3d_camera updated

JavaScript for 3D camera: load a PRC 3D model and align camera with JavaScript.

Download Java Code  Switch to PHP Code  Show Output 

package com.pdflib.cookbook.pdflib.pdf_3D;

import com.pdflib.pdflib;
import com.pdflib.PDFlibException;

/**
 * JavaScript for 3D camera: Load a PRC 3D model and align camera with 
 * JavaScript.
 *
 * Define a 3D view and load some 3D data with the view defined. JavaScript 
 * code positions the camera so its viewing vector is parallel to one of the 
 * x, y, z axes, that it looks towards the center of the bounding box, that a 
 * specific axis points upwards, and that the model is fully viewable.
 * 
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: PRC data file
 */
public class javascript_for_3d_camera {
    /**
     * JavaScript code for viewing the model along the x axis.
     */
    final static String JS_X_AXIS =
        "scene.lightScheme = scene.LIGHT_MODE_DAY;\n"
        
        /*
         * Retrieve bounding box and compute maximum extension of the plane
         * that is looked onto.
         */
        + "var bbox = scene.computeBoundingBox();\n"
        + "var zext = bbox.max.z - bbox.min.z;\n"
        + "var yext = bbox.max.y - bbox.min.y;\n"
        + "var maxext = Math.max(zext, yext);\n"
        
        /*
         * Compute the distance from the bounding box center. This formula was
         * derived heuristically.
         */
        + "var distance = bbox.center.x - bbox.min.x + 3 * maxext;\n"
        
        /*
         * Compute the camera position by adding the distance in the desired
         * direction to the bounding box center.
         */
        + "var cameraOffset = new Vector3(distance, 0, 0);\n"
        + "var cameraPos = new Vector3(bbox.center);\n"
        + "cameraPos.addInPlace(cameraOffset);\n"
        + "var activeCamera = scene.cameras.getByIndex(0);\n"
        
        /*
         * The "up" plane of the camera is determined by pointing towards
         * the viewing direction and by adding an offset to the axis that
         * shall point upwards (the z axis in this case).
         */
        + "activeCamera.up.set(bbox.center.x, bbox.center.y, "
                            + "bbox.center.z + distance);\n"
        
        /*
         * Move the camera to the computed position and point it to the target
         * position.
         */
        + "activeCamera.position.set(cameraPos);\n"
        + "activeCamera.targetPosition.set(bbox.center);\n"
        + "scene.update();";

    /**
     * JavaScript code for viewing the model along the y axis.
     */
    final static String JS_Y_AXIS =
        "scene.lightScheme = scene.LIGHT_MODE_DAY;\n"
        + "var bbox = scene.computeBoundingBox();\n"
        + "var zext = bbox.max.z - bbox.min.z;\n"
        + "var xext = bbox.max.x - bbox.min.x;\n"
        + "var maxext = Math.max(zext, xext);\n"
        + "var distance = bbox.center.y - bbox.min.y + 3 * maxext;\n"
        + "var cameraOffset = new Vector3(0, distance, 0);\n"
        + "var cameraPos = new Vector3(bbox.center);\n"
        + "cameraPos.addInPlace(cameraOffset);\n"
        + "var activeCamera = scene.cameras.getByIndex(0);\n"
        + "activeCamera.up.set(bbox.center.x, bbox.center.y, "
                            + "bbox.center.z + distance);\n"
        + "activeCamera.position.set(cameraPos);\n"
        + "activeCamera.targetPosition.set(bbox.center);\n"
        + "scene.update();";

    /**
     * JavaScript code for viewing the model along the z axis.
     */
    final static String JS_Z_AXIS =
        "scene.lightScheme = scene.LIGHT_MODE_DAY;\n"
        + "var bbox = scene.computeBoundingBox();\n"
        + "var xext = bbox.max.x - bbox.min.x;\n"
        + "var yext = bbox.max.y - bbox.min.y;\n"
        + "var maxext = Math.max(xext, yext);\n"
        + "var distance = bbox.center.z - bbox.min.z + 3 * maxext;\n"
        + "var cameraOffset = new Vector3(0, 0, distance);\n"
        + "var cameraPos = new Vector3(bbox.center);\n"
        + "cameraPos.addInPlace(cameraOffset);\n"
        + "var activeCamera = scene.cameras.getByIndex(0);\n"
        + "activeCamera.up.set(bbox.center.x, bbox.center.y + distance, "
                                    + "bbox.center.z);\n"
        + "activeCamera.position.set(cameraPos);\n"
        + "activeCamera.targetPosition.set(bbox.center);\n"
        + "scene.update();";
    
    public static void main(String argv[]) {
        /* This is where the data files are. Adjust if necessary. */
        String searchpath = "../input";
        String outfile = "javascript_for_3d_camera.pdf";
        String title = "JavaScript for 3D camera";

        pdflib p = null;

        String optlist;
        int font, view;
        int exitcode = 0;

        try {
            p = new pdflib();

            p.set_option("searchpath={" + searchpath + "}");

            /* This means we must check return values of load_font() etc. */
            p.set_option("errorpolicy=return");

            /* Start the document */
            if (p.begin_document(outfile, "") == -1)
                throw new Exception("Error: " + p.get_errmsg());

            p.set_info("Creator", "PDFlib Cookbook");
            p.set_info("Title", title);

            font = p.load_font("NotoSerif-Regular", "unicode", "");
            if (font == -1)
                throw new Exception("Error: " + p.get_errmsg());

            /*
             * Create a 3D view that only defines the background color.
             */
            optlist = "type=PRC background={fillcolor=mediumslateblue}";
            if ((view = p.create_3dview("Default", optlist)) == -1)
                throw new Exception("Error: " + p.get_errmsg());

            make_3d_page(p, font, view, "View model along x axis", JS_X_AXIS);
            make_3d_page(p, font, view, "View model along y axis", JS_Y_AXIS);
            make_3d_page(p, font, view, "View model along z axis", JS_Z_AXIS);

            p.end_document("");
        }
        catch (PDFlibException e) {
            System.err.println("PDFlib exception occurred:");
            System.err.println("[" + e.get_errnum() + "] " + e.get_apiname()
                + ": " + e.get_errmsg());
            exitcode = 1;
        }
        catch (Exception e) {
            System.err.println(e);
            exitcode = 1;
        }
        finally {
            if (p != null) {
                p.delete();
            }
            System.exit(exitcode);
        }
    }

    /**
     * Page width in points (landscape).
     */
    final static int WIDTH = 842;
    
    /**
     * Page height in points (landscape).
     */
    final static int HEIGHT = 595;
    
    /**
     * Margin around textflow and 3D annotation.
     */
    final static int MARGIN = 50;
    
    /**
     * Display the 3D annotation and the JavaScript to position/align the
     * camera side-by-side on a landscape PDF page.
     * 
     * @param p
     *            PDFlib object
     * @param data
     *            3D data
     * @param view
     *            3D default view
     * @param font
     *            font for displaying the JavaScript code
     * @param title
     *            title to display above the JavaScript code
     * @param javascript
     *            JavaScript code to position and align the camera
     * 
     * @throws PDFlibException
     * @throws Exception
     */
    private static void make_3d_page(pdflib p, int font, int view,
            String title, String javascript) throws PDFlibException, Exception {
        String optlist;
        int tf = -1;
        final int element_width = (WIDTH - 3 * MARGIN) / 2;
        final int element_height = HEIGHT - 2 * MARGIN;
        final int tf_xpos = MARGIN;
        final int tf_ypos = MARGIN;
        final int tf_width = element_width;
        final int _3d_xpos = 2 * MARGIN + element_width;
        final int _3d_ypos = MARGIN;
        final int _3d_width = element_width;
        
        optlist = "font=" + font + " fontsize=14 underline=true";
        tf = p.add_textflow(tf, title + "\n\n", optlist);
        optlist = "font=" + font + " fontsize=12 underline=false";
        tf = p.add_textflow(tf, "JavaScript code:\n\n", optlist);
        tf = p.add_textflow(tf, javascript, "");
        
        p.begin_page_ext(WIDTH, HEIGHT, "");

        /* Create a bookmark for jumping to this page */
        p.create_bookmark(title, "");
        
        p.fit_textflow(tf, tf_xpos, tf_ypos,
                tf_xpos + tf_width, tf_ypos + element_height,
                "fitmethod=auto");
        
        /*
         * Load some 3D data with the view defined above
         */
        int data = p.load_3ddata("riemann.prc", "type=PRC views={" + view + "} "
            + "script={" + javascript + "}");
        if (data == -1)
            throw new Exception("Error: " + p.get_errmsg());
        
        /*
         * Create an annotation containing the loaded 3D data with the
         * defined 3D view as the initial view
         */
        optlist = "contents=PRC 3Ddata= " + data + " "
            + "3Dactivate={enable=open} 3Dinitialview=" + view;
        p.create_annotation(_3d_xpos, _3d_ypos, 
            _3d_xpos + _3d_width, _3d_ypos + element_height, "3D",
            optlist);

        p.end_page_ext("");
    }
}