-
Notifications
You must be signed in to change notification settings - Fork 3
/
listing11.html
executable file
·1283 lines (1035 loc) · 40 KB
/
listing11.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>vrmovies - /Common Files/QTVRUtilities.c</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/QuickTime/index.html">QuickTime</a> > <a href="../../samplecode/QuickTime/idxVirtualReality-date.html">Virtual Reality</a> > <A HREF="javascript:location.replace('index.html');">vrmovies</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">vrmovies</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/Common Files/QTVRUtilities.c</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/Application Files/ComApplication.c</option>
<option value="listing2.html">/Application Files/ComApplication.h</option>
<option value="listing3.html">/Application Files/ComResource.h</option>
<option value="listing4.html">/Common Files/ComFramework.c</option>
<option value="listing5.html">/Common Files/ComFramework.h</option>
<option value="listing6.html">/Common Files/MacFramework.c</option>
<option value="listing7.html">/Common Files/MacFramework.h</option>
<option value="listing8.html">/Common Files/MacPrefix.h</option>
<option value="listing9.html">/Common Files/QTUtilities.c</option>
<option value="listing10.html">/Common Files/QTUtilities.h</option>
<option value="listing11.html">/Common Files/QTVRUtilities.c</option>
<option value="listing12.html">/Common Files/QTVRUtilities.h</option>
<option value="listing13.html">/Common Files/WinFramework.c</option>
<option value="listing14.html">/Common Files/WinFramework.h</option>
<option value="listing15.html">/Common Files/WinPrefix.h</option>
<option value="listing16.html">/README.txt</option>
<option value="listing17.html">/VRMovies.c</option>
<option value="listing18.html">/VRMovies.h</option></select>
</p>
</form>
<p><strong><a href="vrmovies.zip">Download Sample</a></strong> (“vrmovies.zip”, 1.00M)<BR>
<strong><a href="vrmovies.dmg">Download Sample</a></strong> (“vrmovies.dmg”, 1.46M)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox">////////////// File: QTVRUtilities.c//// Contains: Some utilities for working with QuickTime VR movies.// All utilities start with the prefix "QTVRUtils_".//// Written by: Tim Monroe//// Copyright: © 1996-1998 by Apple Computer, Inc., all rights reserved.//// Change History (most recent first)://// <26> 09/27/00 rtm modified QTVRUtils_AddStr255ToAtomContainer so it doesn't add a null byte to// the string in the atom container; also added some bullet-proofing// <25> 04/15/99 rtm added QTVRUtils_PanAngleToPoint3D, from Bryce Wolfson// <24> 04/05/99 rtm added QTVRUtils_IsBackBufferHorizontal// <23> 03/11/99 rtm moved _GetControllerType and _SetControllerType to QTUtilities// <22> 02/03/99 rtm moved non-QTVR-specific utilities to QTUtilities// <21> 02/12/98 rtm added QTVRUtils_HideHotSpotNames and her sisters, *Show* and *Toggle*// <20> 01/27/98 rtm revised QTVRUtils_IsQTVRMgrInstalled and QTVRUtils_GetQTVRVersion// <19> 01/26/98 rtm revised QTVRUtils_GetHotSpotName to look also in hot spot atom for name atom// <18> 01/14/98 rtm added QTVRUtils_SetControllerType and QTVRUtils_AddStr255ToAtomContainer// <17> 10/20/97 rtm added QTVRUtils_IsMultiNode; added Endian*_BtoN macros to file format routines// <16> 10/17/97 rtm fixed QTVRUtils_IsControllerButtonVisible behavior for speaker button// <15> 10/07/97 rtm added cannotFindAtomErr result code to QTVRUtils_Get*AtomData functions// <14> 09/15/97 rtm added QTVRUtils_ToggleControllerBar// <13> 08/21/97 rtm added QTVRUtils_IsControllerButtonVisible// <12> 08/19/97 rtm added #ifdefs to support Windows compilation// <11> 08/05/97 rtm added QTVRUtils_GetNodeComment; still needs testing// <10> 07/27/97 rtm fixed QTVRUtils_GetHotSpotCount; added QTVRUtils_GetHotSpotIDByIndex// <9> 07/25/97 rtm revised QTVRUtils_Get*AtomData functions to use QTCopyAtomDataToPtr;// rewrote QTVRUtils_GetStringFromAtom// <8> 07/24/97 rtm removed sound volume utilities; added QTVRUtils_IsZoomAvailable;// revised QTVRUtils_IsQTVRMovie to use GetUserDataItem, not GetUserData// <7> 07/23/97 rtm revised file format utilities; added QTVRUtils_Get*AtomData functions// <6> 07/22/97 rtm fixed QTVRUtils_GetHotSpotCount to make sure handle is actually resized// <5> 07/21/97 rtm added QTVRUtils_GetNodeCount// <4> 06/04/97 rtm fixed QTVRUtils_ShowControllerButton and QTVRUtils_HideControllerButton,// and added some explanation of them; added QTVRUtils_ResetControllerButton// <3> 02/03/97 rtm revised QTVRUtils_ShowControllerButton and QTVRUtils_HideControllerButton // to use explicit flag// <2> 12/03/96 rtm added controller bar utilities// <1> 11/27/96 rtm first file// //////////////////////// header files////////////#ifndef __QTVRUtilities__#include "QTVRUtilities.h"#endif#ifndef __QTUtilities__#include "QTUtilities.h"#endif#include <math.h>#include <stdlib.h>#include <string.h>/////////////////////////////////////////////////////////////////////////////////////////////////////////////// General utilities.//// Use these functions to get information about the availability/features of QuickTime VR or other services./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTVRUtils_IsQTVRMgrInstalled// Is the QuickTime VR Manager installed?////////////Boolean QTVRUtils_IsQTVRMgrInstalled (void) { Boolean myQTVRAvail = false; long myAttrs; OSErr myErr = noErr; myErr = Gestalt(gestaltQTVRMgrAttr, &myAttrs); if (myErr == noErr) if (myAttrs & (1L << gestaltQTVRMgrPresent)) myQTVRAvail = true; return(myQTVRAvail);}////////////// QTVRUtils_GetQTVRVersion// Get the version of the QuickTime VR Manager installed.//// The low-order word of the returned long integer contains the version number,// so you can test a version like this://// if (QTVRUtils_GetQTVRVersion() < 0x0210) // we require QTVR 2.1 or greater// return;////////////long QTVRUtils_GetQTVRVersion (void){ long myVersion = 0L; OSErr myErr = noErr; myErr = Gestalt(gestaltQTVRMgrVers, &myVersion); if (myErr == noErr) return(myVersion); else return(0L);}////////////// QTVRUtils_IsQTVRMovie// Is the specified movie a QTVR movie?//// WARNING: This function is intended for use ONLY when you want to determine if you've got a QTVR movie// but you don't want to use the QuickTime VR API (perhaps QTVR isn't installed...). The preferred way to// determine if a movie is a QTVR movie is to call QTVRGetQTVRTrack and then QTVRGetQTVRInstance; if you// get back a non-NULL instance, you've got a QTVR movie.////////////Boolean QTVRUtils_IsQTVRMovie (Movie theMovie) { Boolean myIsQTVRMovie = false; OSType myType; // QTVR movies have a special piece of user data identifying the movie controller type myType = QTUtils_GetControllerType(theMovie); if ((myType == kQTVRQTVRType) || (myType == kQTVROldPanoType) || (myType == kQTVROldObjectType)) myIsQTVRMovie = true; return(myIsQTVRMovie);}////////////// QTVRUtils_Is20QTVRMovie// Is the specified QTVR movie version 2.0 or greater?////////////Boolean QTVRUtils_Is20QTVRMovie (Movie theMovie) { Boolean myIs20QTVRMovie = false; OSType myType; // QTVR movies have a special piece of user data identifying the movie controller type myType = QTUtils_GetControllerType(theMovie); if (myType == kQTVRQTVRType) myIs20QTVRMovie = true; return(myIs20QTVRMovie);}////////////// QTVRUtils_IsTranslateAvailable// Is translation currently enabled for the specified object node?////////////Boolean QTVRUtils_IsTranslateAvailable (QTVRInstance theInstance) { Boolean myState; QTVRGetControlSetting(theInstance, kQTVRTranslation, &myState); return(myState);}////////////// QTVRUtils_IsZoomAvailable// Is zooming currently enabled for the specified object node?////////////Boolean QTVRUtils_IsZoomAvailable (QTVRInstance theInstance) { Boolean myState; QTVRGetControlSetting(theInstance, kQTVRCanZoom, &myState); return(myState);}////////////// QTVRUtils_IsPanoNode// Is the specified node a panoramic node?////////////Boolean QTVRUtils_IsPanoNode (QTVRInstance theInstance) { return(QTVRGetNodeType(theInstance, kQTVRCurrentNode) == kQTVRPanoramaType);}////////////// QTVRUtils_IsObjectNode// Is the specified node an object node?////////////Boolean QTVRUtils_IsObjectNode (QTVRInstance theInstance) { return(QTVRGetNodeType(theInstance, kQTVRCurrentNode) == kQTVRObjectType);}////////////// QTVRUtils_IsHotSpotInNode// Does the specified node contain at least one hot spot (whether visible, enabled, or whatever)?//// NOTE: This is not an easy function to implement using just the QTVR 2.1 API. We do have our own// utility QTVRUtils_GetHotSpotCount, but that function returns the number of hot spot information atoms// in the node, which is not (necessarily) the number of hot spot regions in the hot spot image track.// For panoramas, we could check to see if the panorama sample atom structure contains a reference// to a hot spot image track; if it does, we'd blindly assume that that track isn't empty. For objects,// we'll have to rely on QTVRUtils_GetHotSpotCount. So it goes....//// In an ideal world, there would be a hot spot information atom for each and every hot spot region in// the hot spot image track, in which case we could be happier using QTVRUtils_GetHotSpotCount.////////////Boolean QTVRUtils_IsHotSpotInNode (QTVRInstance theInstance) { return(QTVRUtils_GetHotSpotCount(theInstance, QTVRGetCurrentNodeID(theInstance), NULL) > 0);}////////////// QTVRUtils_IsMultiNode// Does the specified QuickTime VR instance contain more than one node?////////////Boolean QTVRUtils_IsMultiNode (QTVRInstance theInstance) { return(QTVRUtils_GetNodeCount(theInstance) > (UInt32)1);}////////////// QTVRUtils_IsBackBufferHorizontal// Is the back buffer oriented horizontally?////////////Boolean QTVRUtils_IsBackBufferHorizontal (QTVRInstance theInstance){ UInt32 myGeometry; UInt16 myResolution; UInt32 myCachePixelFormat; SInt16 myCacheSize; OSErr myErr = noErr; if (theInstance == NULL) return(false); myErr = QTVRGetBackBufferSettings(theInstance, &myGeometry, &myResolution, &myCachePixelFormat, &myCacheSize); if (myErr != noErr) return(false); else return(myGeometry == kQTVRHorizontalCylinder);}////////////// QTVRUtils_HideHotSpotNames// Disable the displaying of hot spot names in the controller bar.////////////void QTVRUtils_HideHotSpotNames (MovieController theMC) { QTUtils_HideControllerButton(theMC, kQTUtilsHotSpotNames);}////////////// QTVRUtils_ShowHotSpotNames// Enable the displaying of hot spot names in the controller bar.////////////void QTVRUtils_ShowHotSpotNames (MovieController theMC) { QTUtils_ShowControllerButton(theMC, kQTUtilsHotSpotNames);}////////////// QTVRUtils_ToggleHotSpotNames// Toggle the displaying of hot spot names in the controller bar.////////////void QTVRUtils_ToggleHotSpotNames (MovieController theMC) { QTUtils_ToggleControllerButton(theMC, kQTUtilsHotSpotNames);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// File format utilities.//// Use these functions to read information from QuickTime VR files that's not accessible using the API.// Throughout, we assume that we're dealing with format 2.0 files. We begin with a series of functions that// return a pointer to the data in an atom (QTVRUtils_Get*AtomData); you probably won't use these functions// directly.//// Keep in mind that data stored in QuickTime atoms is big-endian. We'll need to convert any multi-byte data// that we read from an atom to native format before we use it.//// Note that these file format utilities are all Getters. As yet, no Setters. Perhaps later?/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTVRUtils_GetVRWorldHeaderAtomData// Get a pointer to the VR world header atom data in a QTVR movie.////////////OSErr QTVRUtils_GetVRWorldHeaderAtomData (QTVRInstance theInstance, QTVRWorldHeaderAtomPtr theVRWorldHdrAtomPtr){ QTAtomContainer myVRWorld; QTAtom myAtom; OSErr myErr = noErr; // get the VR world myErr = QTVRGetVRWorld(theInstance, &myVRWorld); if (myErr != noErr) return(myErr); // get the single VR world header atom in the VR world myAtom = QTFindChildByIndex(myVRWorld, kParentAtomIsContainer, kQTVRWorldHeaderAtomType, 1, NULL); if (myAtom != 0) myErr = QTCopyAtomDataToPtr(myVRWorld, myAtom, false, sizeof(QTVRWorldHeaderAtom), theVRWorldHdrAtomPtr, NULL); else myErr = cannotFindAtomErr; QTDisposeAtomContainer(myVRWorld); return(myErr);}////////////// QTVRUtils_GetNodeHeaderAtomData// Get a pointer to the node header atom data for the node having the specified node ID.////////////OSErr QTVRUtils_GetNodeHeaderAtomData (QTVRInstance theInstance, UInt32 theNodeID, QTVRNodeHeaderAtomPtr theNodeHdrPtr){ QTAtomContainer myNodeInfo; QTAtom myAtom; OSErr myErr = noErr; // get the node information atom container for the specified node myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); if (myErr != noErr) return(myErr); // get the single node header atom in the node information atom container myAtom = QTFindChildByID(myNodeInfo, kParentAtomIsContainer, kQTVRNodeHeaderAtomType, 1, NULL); if (myAtom != 0) myErr = QTCopyAtomDataToPtr(myNodeInfo, myAtom, false, sizeof(QTVRNodeHeaderAtom), theNodeHdrPtr, NULL); else myErr = cannotFindAtomErr; QTDisposeAtomContainer(myNodeInfo); return(myErr);}////////////// QTVRUtils_GetHotSpotAtomData// Get a pointer to the hot spot atom data for hot spot having the specified hot spot ID in the specified node.////////////OSErr QTVRUtils_GetHotSpotAtomData (QTVRInstance theInstance, UInt32 theNodeID, UInt32 theHotSpotID, QTVRHotSpotInfoAtomPtr theHotSpotInfoPtr){ QTAtomContainer myNodeInfo; QTAtom myHSParentAtom; OSErr myErr = noErr; // (1) the node information atom container contains a *hot spot parent atom*; // (2) the hot spot parent atom contains one or more *hot spot atoms*; // (3) the hot spot atom contains two children, a *general hot spot information atom* // and a *specific hot spot information atom*. // We want to return a pointer to the general hot spot information atom data. // get the node information atom container for the specified node myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); if (myErr != noErr) return(myErr); // get the single hot spot parent atom in the node information atom container myHSParentAtom = QTFindChildByID(myNodeInfo, kParentAtomIsContainer, kQTVRHotSpotParentAtomType, 1, NULL); if (myHSParentAtom != 0) { QTAtom myHSAtom; // get the hot spot atom whose atom ID is the specified hot spot ID myHSAtom = QTFindChildByID(myNodeInfo, myHSParentAtom, kQTVRHotSpotAtomType, theHotSpotID, NULL); if (myHSAtom != 0) { QTAtom myAtom; // get the single hot spot information atom in the hot spot atom myAtom = QTFindChildByIndex(myNodeInfo, myHSAtom, kQTVRHotSpotInfoAtomType, 1, NULL); if (myAtom != 0) { myErr = QTCopyAtomDataToPtr(myNodeInfo, myAtom, false, sizeof(QTVRHotSpotInfoAtom), theHotSpotInfoPtr, NULL); } } else { myErr = cannotFindAtomErr; } } else { myErr = cannotFindAtomErr; } QTDisposeAtomContainer(myNodeInfo); return(myErr);}////////////// QTVRUtils_GetStringFromAtom// Get the string data from the string atom having the specified ID in the specified atom container.//// We use a different strategy here, since we don't know the size of the string data in advance.////////////char *QTVRUtils_GetStringFromAtom (QTAtomContainer theContainer, QTAtom theParent, QTAtomID theID){ QTVRStringAtomPtr myStringAtomPtr = NULL; QTAtom myNameAtom; char *myString = NULL; OSErr myErr = noErr; if (theContainer == NULL) return(myString); QTLockContainer(theContainer); myNameAtom = QTFindChildByID(theContainer, theParent, kQTVRStringAtomType, theID, NULL); if (myNameAtom != 0) { myErr = QTGetAtomDataPtr(theContainer, myNameAtom, NULL, (Ptr *)&myStringAtomPtr); if ((myErr == noErr) && (myStringAtomPtr != NULL)) { UInt16 myLength; myLength = EndianU16_BtoN(myStringAtomPtr->stringLength); if (myLength > 0) { myString = malloc(myLength + 1); if (myString != NULL) { memcpy(myString, myStringAtomPtr->theString, myLength); myString[myLength] = '\0'; } } } } QTUnlockContainer(theContainer); return(myString);}////////////// QTVRUtils_AddStr255ToAtomContainer// Add a Pascal string to the specified atom container; return (through theID) the ID of the new string atom.////////////OSErr QTVRUtils_AddStr255ToAtomContainer (QTAtomContainer theContainer, QTAtom theParent, Str255 theString, QTAtomID *theID){ OSErr myErr = noErr; if ((theContainer == NULL) || (theParent == 0) || (theID == NULL)) return(paramErr); *theID = 0; // initialize the returned atom ID if (theString[0] != 0) { QTAtom myStringAtom; UInt16 mySize; QTVRStringAtomPtr myStringAtomPtr = NULL; mySize = sizeof(QTVRStringAtom) - 4 + theString[0]; myStringAtomPtr = (QTVRStringAtomPtr)NewPtrClear(mySize); if (myStringAtomPtr != NULL) { myStringAtomPtr->stringUsage = EndianU16_NtoB(1); myStringAtomPtr->stringLength = EndianU16_NtoB(theString[0]); BlockMove(theString + 1, myStringAtomPtr->theString, theString[0]); myErr = QTInsertChild(theContainer, theParent, kQTVRStringAtomType, 0, 0, mySize, (Ptr)myStringAtomPtr, &myStringAtom); DisposePtr((Ptr)myStringAtomPtr); if (myErr == noErr) QTGetAtomTypeAndID(theContainer, myStringAtom, NULL, theID); } } return(myErr);}////////////// QTVRUtils_GetDefaultNodeID// Get the ID of the default node in a QTVR movie.////////////UInt32 QTVRUtils_GetDefaultNodeID (QTVRInstance theInstance){ QTVRWorldHeaderAtom myVRWorldHeader; UInt32 myNodeID = kQTVRCurrentNode; OSErr myErr = noErr; myErr = QTVRUtils_GetVRWorldHeaderAtomData(theInstance, &myVRWorldHeader); if (myErr == noErr) myNodeID = EndianU32_BtoN(myVRWorldHeader.defaultNodeID); return(myNodeID);}////////////// QTVRUtils_GetSceneFlags// Get the set of flags associated with the VR scene.// (Currently these flags are undefined, however.)////////////UInt32 QTVRUtils_GetSceneFlags (QTVRInstance theInstance){ QTVRWorldHeaderAtom myVRWorldHeader; UInt32 myFlags = 0L; OSErr myErr; myErr = QTVRUtils_GetVRWorldHeaderAtomData(theInstance, &myVRWorldHeader); if (myErr == noErr) myFlags = EndianU32_BtoN(myVRWorldHeader.vrWorldFlags); return(myFlags);}////////////// QTVRUtils_GetSceneName// Get the name of the VR scene.// The caller is responsible for disposing of the pointer returned by this function (by calling free).////////////char *QTVRUtils_GetSceneName (QTVRInstance theInstance){ QTVRWorldHeaderAtom myVRWorldHeader; char *mySceneName = NULL; OSErr myErr = noErr; myErr = QTVRUtils_GetVRWorldHeaderAtomData(theInstance, &myVRWorldHeader); if (myErr == noErr) { QTAtomID myNameAtomID; // get the atom ID of the name string atom myNameAtomID = EndianU32_BtoN(myVRWorldHeader.nameAtomID); if (myNameAtomID != 0) { QTAtomContainer myVRWorld; // the string atom containing the name of the scene is a *sibling* of the VR world header atom myErr = QTVRGetVRWorld(theInstance, &myVRWorld); if (myErr == noErr) mySceneName = QTVRUtils_GetStringFromAtom(myVRWorld, kParentAtomIsContainer, myNameAtomID); QTDisposeAtomContainer(myVRWorld); } } return(mySceneName);}////////////// QTVRUtils_GetNodeCount// Get the number of nodes in a QTVR movie.////////////UInt32 QTVRUtils_GetNodeCount (QTVRInstance theInstance){ QTAtomContainer myVRWorld; QTAtom myNodeParentAtom; UInt32 myNumNodes = 0; OSErr myErr = noErr; // get the VR world myErr = QTVRGetVRWorld(theInstance, &myVRWorld); if (myErr != noErr) return(myNumNodes); // get the node parent atom, whose children contain info about all nodes in the scene myNodeParentAtom = QTFindChildByIndex(myVRWorld, kParentAtomIsContainer, kQTVRNodeParentAtomType, 1, NULL); if (myNodeParentAtom != 0) { // now count the node ID children of the node parent atom, which is the number of nodes in the scene myNumNodes = QTCountChildrenOfType(myVRWorld, myNodeParentAtom, kQTVRNodeIDAtomType); } QTDisposeAtomContainer(myVRWorld); return(myNumNodes);}////////////// QTVRUtils_GetNodeType// Get the type of the node with the specified ID.//// NOTE: This function is redundant, given QTVRGetNodeType; it's included here for illustrative purposes only.////////////OSErr QTVRUtils_GetNodeType (QTVRInstance theInstance, UInt32 theNodeID, OSType *theNodeType){ QTVRNodeHeaderAtom myNodeHeader; OSErr myErr = noErr; // make sure we always return some meaningful value *theNodeType = kQTVRUnknownType; // get the node header atom data myErr = QTVRUtils_GetNodeHeaderAtomData(theInstance, theNodeID, &myNodeHeader); if (myErr == noErr) *theNodeType = EndianU32_BtoN(myNodeHeader.nodeType); return(myErr);}////////////// QTVRUtils_GetNodeName// Get the name of the node with the specified ID.// The caller is responsible for disposing of the pointer returned by this function (by calling free).////////////char *QTVRUtils_GetNodeName (QTVRInstance theInstance, UInt32 theNodeID){ QTVRNodeHeaderAtom myNodeHeader; char *myNodeName = NULL; OSErr myErr = noErr; myErr = QTVRUtils_GetNodeHeaderAtomData(theInstance, theNodeID, &myNodeHeader); if (myErr == noErr) { QTAtomID myNameAtomID; // get the atom ID of the name string atom myNameAtomID = EndianU32_BtoN(myNodeHeader.nameAtomID); if (myNameAtomID != 0) { QTAtomContainer myNodeInfo; // the string atom containing the name of the node is a *sibling* of the node information atom myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); if (myErr == noErr) myNodeName = QTVRUtils_GetStringFromAtom(myNodeInfo, kParentAtomIsContainer, myNameAtomID); QTDisposeAtomContainer(myNodeInfo); } } return(myNodeName);}////////////// QTVRUtils_GetNodeComment// Get the comment for the node with the specified ID.// The caller is responsible for disposing of the pointer returned by this function (by calling free).////////////char *QTVRUtils_GetNodeComment (QTVRInstance theInstance, UInt32 theNodeID){ QTVRNodeHeaderAtom myNodeHeader; char *myNodeCmt = NULL; OSErr myErr = noErr; myErr = QTVRUtils_GetNodeHeaderAtomData(theInstance, theNodeID, &myNodeHeader); if (myErr == noErr) { QTAtomID myCmtAtomID; // get the atom ID of the comment string atom myCmtAtomID = EndianU32_BtoN(myNodeHeader.commentAtomID); if (myCmtAtomID != 0) { QTAtomContainer myNodeInfo; // the string atom containing the comment for the node is a *sibling* of the node information atom myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); if (myErr == noErr) myNodeCmt = QTVRUtils_GetStringFromAtom(myNodeInfo, kParentAtomIsContainer, myCmtAtomID); QTDisposeAtomContainer(myNodeInfo); } } return(myNodeCmt);}////////////// QTVRUtils_GetHotSpotCount// Return the number of hot spots in the node with specified ID,// and fill the specified handle with a list of the hot spot IDs.//// If theHotSpotIDs == NULL on entry, do not pass back the list of IDs.//// WARNING: This routine determines the number of hot spots by counting// the hot spot atoms in a hot spot parent atom; this might not be// the same as counting the number of regions in the hot spot image track.// Sigh.////////////UInt32 QTVRUtils_GetHotSpotCount (QTVRInstance theInstance, UInt32 theNodeID, Handle theHotSpotIDs){ QTAtomContainer myNodeInfo; QTAtom myHSParentAtom = 0; UInt32 myNumHotSpots = 0; OSErr myErr = noErr; // get the node information atom container for the current node myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); // get the hot spot parent atom if (myErr == noErr) myHSParentAtom = QTFindChildByID(myNodeInfo, kParentAtomIsContainer, kQTVRHotSpotParentAtomType, 1, NULL); if (myHSParentAtom != 0) { SignedByte myHState; Size mySize; // get the number of hot spots in the current node myNumHotSpots = QTCountChildrenOfType(myNodeInfo, myHSParentAtom, kQTVRHotSpotAtomType); // now pass back a list of the hot spot IDs; // if theHotSpotIDs is NULL on entry, we assume the caller doesn't want this information if (theHotSpotIDs != NULL) { // unlock the handle, if it's locked (so that we can resize it) myHState = HGetState(theHotSpotIDs); if (myHState & 0x80) // 0x80 == the block-is-locked bit in the SignedByte returned by HGetState HUnlock(theHotSpotIDs); // resize the handle to the appropriate size mySize = sizeof(UInt32) * myNumHotSpots; SetHandleSize(theHotSpotIDs, mySize); // restore the original handle state HSetState(theHotSpotIDs, myHState); // make sure we actually did resize the handle if (GetHandleSize(theHotSpotIDs) == mySize) { short myIndex; QTAtom myAtom; QTAtomID myID; UInt32 *myIDPtr; myIDPtr = (UInt32 *)*theHotSpotIDs; // loop thru all the hot spots to get their IDs for (myIndex = 1; myIndex <= (short)myNumHotSpots; myIndex++) { myAtom = QTFindChildByIndex(myNodeInfo, myHSParentAtom, kQTVRHotSpotAtomType, myIndex, &myID); myIDPtr[myIndex - 1] = (UInt32)myID; } } } } QTDisposeAtomContainer(myNodeInfo); return(myNumHotSpots);}////////////// QTVRUtils_GetHotSpotIDByIndex// Return the hot spot ID having the specified index in the list of hot spot IDs returned by QTVRUtils_GetHotSpotCount,// or kQTVRUtils_InvalidHotSpotID if no such hot spot exists.////////////UInt32 QTVRUtils_GetHotSpotIDByIndex (QTVRInstance theInstance, Handle theHotSpotIDs, UInt32 theIndex){ Size mySize; UInt32 myID = kQTVRUtils_InvalidHotSpotID; UInt32 *myIDPtr; // make sure the instance and hot spot list are non-NULL if ((theInstance == NULL) || (theHotSpotIDs == NULL)) return(myID); // make sure that the index is valid mySize = GetHandleSize(theHotSpotIDs); if (theIndex >= (mySize / sizeof(UInt32))) return(myID); myIDPtr = (UInt32 *)*theHotSpotIDs; myID = myIDPtr[theIndex]; return(myID);}////////////// QTVRUtils_GetHotSpotType// Return the type of the hot spot having the specified hot spot ID in the specified node.//// NOTE: This function is semi-redundant, given QTVRGetHotSpotType; it's included here for illustrative purposes only.// (Note, however, that QTVRGetHotSpotType returns types only for hot spots in the current node; here we do any node!)////////////OSErr QTVRUtils_GetHotSpotType (QTVRInstance theInstance, UInt32 theNodeID, UInt32 theHotSpotID, OSType *theHotSpotType){ QTVRHotSpotInfoAtom myHotSpotAtomData; OSErr myErr = noErr; // make sure we always return some meaningful value *theHotSpotType = kQTVRHotSpotUndefinedType; // get the hot spot information atom data myErr = QTVRUtils_GetHotSpotAtomData(theInstance, theNodeID, theHotSpotID, &myHotSpotAtomData); if (myErr == noErr) *theHotSpotType = EndianU32_BtoN(myHotSpotAtomData.hotSpotType); // return the hot spot type return(myErr);}////////////// QTVRUtils_GetHotSpotName// Return the name of the hot spot having the specified hot spot ID in the specified node.// The caller is responsible for disposing of the pointer returned by this function (by calling free).////////////char *QTVRUtils_GetHotSpotName (QTVRInstance theInstance, UInt32 theNodeID, UInt32 theHotSpotID){ QTVRHotSpotInfoAtom myHotSpotAtomData; char *myHotSpotName = NULL; OSErr myErr = noErr; // get the hot spot information atom data myErr = QTVRUtils_GetHotSpotAtomData(theInstance, theNodeID, theHotSpotID, &myHotSpotAtomData); if (myErr == noErr) { QTAtomID myNameAtomID; // get the atom ID of the name string atom myNameAtomID = EndianU32_BtoN(myHotSpotAtomData.nameAtomID); if (myNameAtomID != 0) { QTAtomContainer myNodeInfo; QTAtom myHSParentAtom; QTAtom myHSAtom; QTAtom myNameAtom = 0; // version 2.0 documentation says that the hot spot name is contained in a string atom // that is a sibling of the hot spot atom (that is, a child of the hot spot parent atom); // some other documents indicate that a string atom is always a sibling of the atom that // contains the reference (in this case, a sibling of the hot spot information atom, and // hence a child of the hot spot atom); we will look first in the hot spot atom and then // in the hot spot parent atom. The version 2.1 documentation corrects the earlier error. // Mea culpa! // get the hot spot parent atom and the hot spot atom myErr = QTVRGetNodeInfo(theInstance, theNodeID, &myNodeInfo); if (myErr == noErr) { myHSParentAtom = QTFindChildByID(myNodeInfo, kParentAtomIsContainer, kQTVRHotSpotParentAtomType, 1, NULL); if (myHSParentAtom != 0) { myHSAtom = QTFindChildByID(myNodeInfo, myHSParentAtom, kQTVRHotSpotAtomType, theHotSpotID, NULL); if (myHSAtom != 0) { QTAtom myParentAtom; // look for a string atom that is a child of the hot spot atom myParentAtom = myHSAtom; myNameAtom = QTFindChildByID(myNodeInfo, myParentAtom, kQTVRStringAtomType, theHotSpotID, NULL); if (myNameAtom == 0) { // no such atom in the hot spot atom; look in the hot spot parent atom myParentAtom = myHSParentAtom; myNameAtom = QTFindChildByID(myNodeInfo, myParentAtom, kQTVRStringAtomType, theHotSpotID, NULL); } if (myNameAtom != 0) myHotSpotName = QTVRUtils_GetStringFromAtom(myNodeInfo, myParentAtom, myNameAtomID); } } } QTDisposeAtomContainer(myNodeInfo); } } return(myHotSpotName);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Miscellaneous utilities./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTVRUtils_Point3DToPanAngle// Return the QTVR pan angle for a given QD3D point.// //////////float QTVRUtils_Point3DToPanAngle (float theX, float theY, float theZ){#pragma unused(theY) float myPan; if (theZ != 0.0) { // note that atan always returns angles in the range -¹/2 to ¹/2 myPan = atan(theX / theZ); myPan = (theZ > 0) ? myPan + kVRPi : myPan; } else { myPan = (theX > 0) ? kVR3PiOver2 : kVRPiOver2; } // make sure myPan is positive while (myPan < 0.0) myPan += kVR2Pi; return(myPan);}////////////// QTVRUtils_Point3DToTiltAngle// Return the QTVR tilt angle for a given QD3D point.// //////////float QTVRUtils_Point3DToTiltAngle (float theX, float theY, float theZ){ float myTilt; float myDistance; TQ3Point3D myPoint; myPoint.x = theX; myPoint.y = theY; myPoint.z = theZ; myDistance = QTVRUtils_GetDistance(myPoint); if (myDistance != 0.0) myTilt = asin(theY / myDistance); else myTilt = 0.0; return(myTilt);}////////////// QTVRUtils_PanAngleToPoint3D// Return a unit vector for a given QTVR pan angle.//// The pan angle is expected to be in radians.// //////////void QTVRUtils_PanAngleToPoint3D (float thePanAngle, float *theX, float *theZ){ // sin and cos are continuous functions and have no limits on input range; // output range is always -1..1 *theX = sin(thePanAngle); *theZ = -cos(thePanAngle);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Node callback utilities.//// Use these to obtain standard behaviors when entering or exiting nodes./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTVRUtils_StandardEnteringNodeProc// A standard procedure for entering a new node.//// This function performs actions that many applications will want done when entering a new node:// * display back button only if multinode movie// * display show-hot-spot button only if there are hotspots// * display the translate button only for object nodes that can translate// * (this space for rent)////////////PASCAL_RTN OSErr QTVRUtils_StandardEnteringNodeProc (QTVRInstance theInstance, long theNodeID, MovieController theMC){#pragma unused(theNodeID) OSErr myErr = noErr; if ((theInstance == NULL) || (theMC == NULL)) return(paramErr); /////// // all nodes /////// // display the back button only if it's a multinode movie if (QTVRUtils_IsMultiNode(theInstance)) QTUtils_ShowControllerButton(theMC, kQTUtilsBackButton); else QTUtils_HideControllerButton(theMC, kQTUtilsBackButton); // display the show-hot-spot button only if there are hotspots in the node if (QTVRUtils_IsHotSpotInNode(theInstance)) QTUtils_ShowControllerButton(theMC, kQTUtilsHotSpotButton); else QTUtils_HideControllerButton(theMC, kQTUtilsHotSpotButton); /////// // panoramic nodes /////// if (QTVRUtils_IsPanoNode(theInstance)) { // hide the translate button QTUtils_HideControllerButton(theMC, kQTUtilsTranslateButton); } else { /////// // object nodes /////// // show the translate button, but only if translation is available if (QTVRUtils_IsTranslateAvailable(theInstance)) QTUtils_ShowControllerButton(theMC, kQTUtilsTranslateButton); else QTUtils_HideControllerButton(theMC, kQTUtilsTranslateButton); } return(myErr);}////////////// QTVRUtils_StandardLeavingNodeProc// A standard procedure for leaving a node.// This function performs actions that many applications will want done when leaving a node:// * (this space for rent)//// We assume that when this procedure is called, the application has decided NOT to cancel the move;// accordingly, we always return false in theCancel.////////////PASCAL_RTN OSErr QTVRUtils_StandardLeavingNodeProc (QTVRInstance theInstance, long fromNodeID, long toNodeID, Boolean *theCancel, MovieController theMC){#pragma unused(fromNodeID, toNodeID) OSErr myErr = noErr; if ((theInstance == NULL) || (theMC == NULL)) return(paramErr); // nothing yet.... *theCancel = false; return(myErr);}</pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/vrmovies/listing11.html%3Fid%3DDTS10001030-1.0&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/vrmovies/listing11.html%3Fid%3DDTS10001030-1.0&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/vrmovies/listing11.html%3Fid%3DDTS10001030-1.0&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>