src/TweenCamera.java

/*
 * QuickTime for Java SDK Sample Code
 
   Usage subject to restrictions in SDK License Agreement
 * Copyright: © 1996-1999 Apple Computer, Inc.
 
 */
import java.io.*;
 
import quicktime.*;
import quicktime.io.*;
import quicktime.std.*;
import quicktime.util.*;
import quicktime.qd.*;
import quicktime.qd3d.camera.*;
import quicktime.qd3d.math.*;
import quicktime.std.movies.*;
import quicktime.std.movies.media.*;
import quicktime.app.QTFactory;
 
public class TweenCamera implements StdQTConstants {
    public static void main (String args[]) {
        try {
            System.out.println ("This will open the jet.mov and add a tween track to it, saving the result to the original movie");
            QTSession.open();
            makeMovie ();
            System.out.println ("Finished");
        }
        catch (Exception e) {
            e.printStackTrace();
        } finally {
            QTSession.close();
        }
    }
        
    private static void makeMovie () throws Exception {
        // Get the 3d movie file from the user
        QTFile movieFile = new QTFile (QTFactory.findAbsolutePath ("jet.mov"));
        System.out.println (movieFile);
        OpenMovieFile instream = OpenMovieFile.asRead(movieFile);
        Movie myMovie = Movie.fromFile(instream);
        instream.close();
 
        // get the 3d track and media from the movie
        Track threeDTrack = myMovie.getIndTrack(1);
        ThreeDMedia threeDMedia = (ThreeDMedia) Media.getTrackMedia(threeDTrack);
 
        // make a tween track and media
        Track tweenTrack = myMovie.addTrack(0, 0, 0);
        TweenMedia tweenMedia = new TweenMedia(tweenTrack, threeDMedia.getTimeScale());
 
        // make empty tween sample
        AtomContainer tweenSample = new AtomContainer();
        
        // Construct shared data for the two camera descriptions
        Point3D cameraTo = new Point3D (0.0F, 0.0F, 0.0F);
        Vector3D cameraUp = new Vector3D (0.0F, 1.0F, 0.0F);
        
        float hither = 0.001F;
        float yon = 1000.0F;
        CameraRange range = new CameraRange(hither, yon);
        
        QDPoint origin = new QDPoint (-1.0F, 1.0F);
        float width = 2.0F;
        float height = 2.0F;
        CameraViewPort cameraView = new CameraViewPort (origin, width, height);
        
 
//**    addTweenEntryToSample ...   sets the type of the tween  
            Point3D cameraFrom = new Point3D(0.0F, 0.0F, 30.0F);
            CameraData tweenCamera = new CameraData(new CameraPlacement(cameraFrom, cameraTo, cameraUp), range, cameraView);
 
            // create entry for this tween in the sample
            Atom tweenAtom = tweenSample.insertChild (new Atom(kParentAtomIsContainer), kTweenEntry, 1, 0);
 
            // define the type of this tween entry
            tweenSample.insertChild(tweenAtom, kTweenType, 1, 0, EndianOrder.flipNativeToBigEndian32(kTweenType3dCameraData));
            
            //Endian flip tweenCamera in place
            EndianOrder.flipNativeToBigEndian (tweenCamera, 0, CameraData.getEndianDescriptor());
            
            // define the 'flipped' data for this tween entry
            tweenSample.insertChild(tweenAtom, kTweenData, 1, 0, tweenCamera);
 
//**    setTweenEntryInitialConditions
        // Set camera initial conditions => the only difference is the initialLocation
        // but because the camera data may have been flipped we create a clean copy
        // we could have cloned this and then flipped it but this way we are explicit about dealing with 
        // two different camera stuctures (even though they share values)
        
            // modify coordinates
            Point3D initialLocation = new Point3D (0, 0, 150.0F);
            CameraData initialCamera = new CameraData(new CameraPlacement(initialLocation, cameraTo, cameraUp), range, cameraView);
 
            // look up the tween entry
            Atom initialTweenAtom = tweenSample.findChildByID_Atom (new Atom(kParentAtomIsContainer), kTweenEntry, 1);
 
            //Endian flip tweenCamera in place
            EndianOrder.flipNativeToBigEndian (initialCamera, 0, CameraData.getEndianDescriptor());
 
            // add in the intial 'flipped' data
            tweenSample.insertChild (initialTweenAtom, kTween3dInitialCondition, 1, 0, initialCamera); 
 
//**    addTweenEntryToInputMapEntry
            // make up tween sample description
            ThreeDDescription sampleDescription = new ThreeDDescription(0);
            
            // add the tween sample to the tween media
            tweenMedia.beginEdits();
            tweenMedia.addSample(tweenSample, 0, tweenSample.getSize(), threeDMedia.getDuration(),
                                                     sampleDescription, 1, 0);
            tweenMedia.endEdits();
            
            // add the tween media into the track
            tweenTrack.insertMedia(0, 0, tweenMedia.getDuration(), 1);
 
            // create the reference between the 3d and tween tracks
            int referenceIndex1 = threeDTrack.addReference(tweenTrack, kTrackModifierReference);
            
            // create input map for 3d track
            AtomContainer inputMap = new AtomContainer();
 
            // add an input entry to the input map
            Atom inputAtom = inputMap.insertChild (new Atom(kParentAtomIsContainer), kTrackModifierInput, referenceIndex1, 0);
            
            // set the type of the modifier input
            inputMap.insertChild(inputAtom, kTrackModifierType, 1, 0, EndianOrder.flipNativeToBigEndian32(kTrackModifierCameraData));
            
            // set the sub input id (the id of the tween entry)
            inputMap.insertChild(inputAtom, kInputMapSubInputID, 1, 0, EndianOrder.flipNativeToBigEndian32(1));
 
//** attach the input map to the 3d media handler
            threeDMedia.setInputMap(inputMap);
 
//** save the newly created movie
            OpenMovieFile outstream = OpenMovieFile.asWrite(movieFile);
            myMovie.updateResource(outstream, movieInDataForkResID, movieFile.getName());
            outstream.close();
    }
}