3D Graphics Programming with QuickDraw 3D
Listing 4-1 illustrates how to create a retained box.
Listing 4-1 Creating a retained box
TQ3GeometryObject myBox; TQ3BoxData myBoxData; Q3Point3D_Set(&myBoxData.origin, 1.0, 1.0, 1.0); Q3Vector3D_Set(&myBoxData.orientation, 0, 2.0, 0); Q3Vector3D_Set(&myBoxData.minorAxis, 2.0, 0, 0); Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 2.0); myBox = Q3Box_New(&myBoxData);Once the code in Listing 4-1 has been executed, the variable
myBox
contains a reference to the new box. You can then reuse or dispose of the myBoxData
structure, because all subsequent operations on the retained box are performed using myBox
. For example, to submit the box for drawing, picking, bounding, or writing, you can execute the following line of code inside a rendering, picking, bounding, or writing loop:
myStatus = Q3Object_Submit(myBox, myView);To dispose of the retained box, you can call the
Q3Object_Dispose
function,
myStatus = Q3Object_Dispose(myBox);Listing 4-2 illustrates how to create an immediate box.
Listing 4-2 Creating an immediate box
TQ3BoxData myBoxData; Q3Point3D_Set(&myBoxData.origin, 1.0, 1.0, 1.0); Q3Vector3D_Set(&myBoxData.orientation, 0, 2.0, 0); Q3Vector3D_Set(&myBoxData.minorAxis, 2.0, 0, 0); Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 2.0);As you can see, you do not have to call any QuickDraw3D routine to create an immediate box; instead, you simply define the box data in a structure of type
TQ3BoxData
. To draw an immediate box, you call the Q3Box_Submit
function (inside a rendering loop), as follows:
myStatus = Q3Box_Submit(myBox, myView);Because you didn't create any retained entity, you do not need to dispose of the immediate box.
Q3Mesh_New
to create a new empty mesh and then by calling Q3Mesh_VertexNew
and Q3Mesh_FaceNew
to explicitly add vertices and faces Listing 4-3 Creating a simple mesh
TQ3GroupObject MyBuildMesh (void) { TQ3ColorRGB myMeshColor; TQ3GroupObject myModel; static TQ3Vertex3D vertices[9] = { { { -0.5, 0.5, 0.0 }, NULL }, { { -0.5, -0.5, 0.0 }, NULL }, { { 0.0, -0.5, 0.3 }, NULL }, { { 0.5, -0.5, 0.0 }, NULL }, { { 0.5, 0.5, 0.0 }, NULL }, { { 0.0, 0.5, 0.3 }, NULL }, { { -0.4, 0.2, 0.0 }, NULL }, { { 0.0, 0.0, 0.0 }, NULL }, { { -0.4, -0.2, 0.0 }, NULL }}; static TQ3Param2D verticesUV[9] = { {0.0, 1.0}, {0.0, 0.0}, {0.5, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.5, 1.0}, {0.1, 0.8}, {0.5, 0.5}, {0.1, 0.4}}; TQ3MeshVertex myMeshVertices[9]; TQ3GeometryObject myMesh; TQ3MeshFace myMeshFace; TQ3AttributeSet myFaceAttrs; unsigned long i; myMesh = Q3Mesh_New(); /*create new empty mesh*/ Q3Mesh_DelayUpdates(myMesh); /*turn off mesh updating*/ /*Add vertices and surface parameterization to mesh.*/ for (i = 0; i < 9; i++) { TQ3AttributeSet myVertAttrs; myMeshVertices[i] = Q3Mesh_VertexNew(myMesh, &vertices[i]); myVertAttrs = Q3AttributeSet_New(); Q3AttributeSet_Add (myVertAttrs, kQ3AttributeTypeSurfaceUV, &verticesUV[i]); Q3Mesh_SetVertexAttributeSet(myMesh, myMeshVertices[i], myVertAttrs); Q3Object_Dispose(myVertAttrs); } myFaceAttrs = Q3AttributeSet_New(); myMeshColor.r = 0.3; myMeshColor.g = 0.9; myMeshColor.b = 0.5; Q3AttributeSet_Add (myFaceAttrs, kQ3AttributeTypeDiffuseColor, &myMeshColor); myMeshFace = Q3Mesh_FaceNew(myMesh, 6, myMeshVertices, myFaceAttrs); Q3Mesh_FaceToContour(myMesh, myMeshFace, Q3Mesh_FaceNew(myMesh, 3, &myMeshVertices[6], NULL)); Q3Mesh_ResumeUpdates(myMesh); myModel = Q3OrderedDisplayGroup_New(); Q3Group_AddObject(myModel, myMesh); Q3Object_Dispose(myFaceAttrs); Q3Object_Dispose(myMesh); return (myModel); }The new mesh created by MyBuildMesh is a retained object. Note that you need to call
Q3Mesh_New
before you call Q3Mesh_VertexNew
and Q3Mesh_FaceNew
. Also, the call to Q3Mesh_FaceToContour
destroys any attributes associated with the mesh face that is turned into a contour.Q3Mesh_FirstMeshFace
function to get the first face in the mesh and then by calling Q3Mesh_NextMeshFace
to get each successive face in the mesh. When you call Q3Mesh_FirstMeshFace
, you specify a mesh and a mesh iterator structure, which QuickDraw3D fills in with information about its current position while traversing a mesh. You must pass that same mesh iterator structure to Q3Mesh_NextMeshFace
when you get successive faces in the mesh. Listing 4-4 illustrates how to use these routines to operate on all faces in a mesh.Listing 4-4 Iterating through all faces in a mesh
TQ3Status MySetMeshFacesDiffuseColor (TQ3GeometryObject myMesh,
TQ3ColorRGB color)
{
TQ3MeshFace myFace;
TQ3MeshIterator myIter;
TQ3Status myErr;
TQ3AttributeSet mySet;
for (myFace = Q3Mesh_FirstMeshFace(myMesh, &myIter);
myFace;
myFace = Q3Mesh_NextMeshFace
(&myIter)) {
/*Get the current attribute set of the current face.*/
myErr = Q3Mesh_GetFaceAttributeSet(myMesh, myFace, &mySet);
if (myErr == kQ3Failure) return (kQ3Failure);
/*Add the color attribute to the face attribute set.*/
myErr = Q3AttributeSet_Add((TQ3AttributeSet)mySet,
kQ3AttributeTypeDiffuseColor, &color);
if (myErr == kQ3Failure) return (kQ3Failure);
/*Set the attribute set of the current face.*/
myErr = Q3Mesh_SetFaceAttributeSet(myMesh, myFace, mySet);
if (myErr == kQ3Failure) return (kQ3Failure);
}
return (kQ3Success);
}
QuickDraw3D also supplies a number of C language macros that you can use to simplify your source code. For example, you can use the Q3ForEachMeshFace
macro, defined like this:
#define Q3ForEachMeshFace(m,f,i) \ for ( (f) = Q3Mesh_FirstMeshFace((m),(i)); \ (f); \ (f) = Q3Mesh_NextMeshFace((i)) )Listing 4-5 shows how to use two of these macros to attach a corner to each vertex or each face of a mesh.
Listing 4-5 Attaching corners to all vertices in all faces of a mesh
TQ3Status MyAddCornersToMesh (TQ3GeometryObject myMesh,
TQ3AttributeSet mySet)
{
TQ3MeshFace myFace;
TQ3MeshVertex myVertex;
TQ3MeshIterator myIter1;
TQ3MeshIterator myIter2;
TQ3Status myErr;
Q3ForEachMeshFace(myMesh, myFace, &myIter1) {
Q3ForEachFaceVertex(myFace, myVertex, &myIter2) {
myErr = Q3Mesh_SetCornerAttributeSet
(myMesh, myFace, myVertex, mySet);
if (myErr == kQ3Failure) return (kQ3Failure);
}
}
return (kQ3Success);
}
Let us know what you think of these prototype pages.
Generated with Harlequin WebMaker