1 /*  NAME:
2         E3GeometryDisk.c
3 
4     DESCRIPTION:
5         Implementation of Quesa Pixmap Marker geometry class.
6 
7     COPYRIGHT:
8         Copyright (c) 1999-2005, Quesa Developers. All rights reserved.
9 
10         For the current release of Quesa, please see:
11 
12             <http://www.quesa.org/>
13 
14         Redistribution and use in source and binary forms, with or without
15         modification, are permitted provided that the following conditions
16         are met:
17 
18             o Redistributions of source code must retain the above copyright
19               notice, this list of conditions and the following disclaimer.
20 
21             o Redistributions in binary form must reproduce the above
22               copyright notice, this list of conditions and the following
23               disclaimer in the documentation and/or other materials provided
24               with the distribution.
25 
26             o Neither the name of Quesa nor the names of its contributors
27               may be used to endorse or promote products derived from this
28               software without specific prior written permission.
29 
30         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31         "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32         LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33         A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34         OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35         SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
36         TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37         PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
38         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40         SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41     ___________________________________________________________________________
42 */
43 //=============================================================================
44 //      Include files
45 //-----------------------------------------------------------------------------
46 #include "E3Prefix.h"
47 #include "E3View.h"
48 #include "E3Geometry.h"
49 #include "E3GeometryDisk.h"
50 #include "E3ErrorManager.h"
51 
52 
53 
54 
55 
56 //=============================================================================
57 //      Internal types
58 //-----------------------------------------------------------------------------
59 
60 class E3Disk : public E3Geometry // This is a leaf class so no other classes use this,
61 								// so it can be here in the .c file rather than in
62 								// the .h file, hence all the fields can be public
63 								// as nobody should be including this file
64 	{
65 Q3_CLASS_ENUMS ( kQ3GeometryTypeDisk, E3Disk, E3Geometry )
66 public :
67 
68 	TQ3DiskData			instanceData ;
69 
70 	} ;
71 
72 
73 
74 //=============================================================================
75 //      Internal functions
76 //-----------------------------------------------------------------------------
77 //      e3geom_disk_new : Disk new method.
78 //-----------------------------------------------------------------------------
79 static TQ3Status
80 e3geom_disk_new(TQ3Object theObject, void *privateData, const void *paramData)
81 {	TQ3DiskData			*instanceData = (TQ3DiskData *)       privateData;
82 	const TQ3DiskData	*diskData     = (const TQ3DiskData *) paramData;
83 	TQ3Status			qd3dStatus;
84 
85 
86 
87 	// Initialise our instance data
88 	Q3Memory_Clear(instanceData, sizeof(TQ3DiskData));
89 
90 	qd3dStatus = Q3Disk_SetData(theObject, diskData);
91 
92 	return(qd3dStatus);
93 }
94 
95 
96 
97 
98 
99 //=============================================================================
100 //      e3geom_disk_delete : Disk delete method.
101 //-----------------------------------------------------------------------------
102 static void
103 e3geom_disk_delete(TQ3Object theObject, void *privateData)
104 {	TQ3DiskData		*instanceData = (TQ3DiskData *) privateData;
105 	TQ3Status		qd3dStatus;
106 #pragma unused(theObject)
107 
108 
109 
110 	// Dispose of our instance data
111 	qd3dStatus = Q3Disk_EmptyData(instanceData);
112 }
113 
114 
115 
116 
117 
118 //=============================================================================
119 //      e3geom_disk_duplicate : Disk duplicate method.
120 //-----------------------------------------------------------------------------
121 static TQ3Status
122 e3geom_disk_duplicate(TQ3Object fromObject, const void *fromPrivateData,
123 					  TQ3Object toObject,   void       *toPrivateData)
124 {	TQ3DiskData			*toInstanceData = (TQ3DiskData *) toPrivateData;
125 	TQ3Status			qd3dStatus;
126 	TQ3AttributeSet		dupSet;
127 #pragma unused(fromPrivateData)
128 #pragma unused(toObject)
129 
130 
131 
132 	// Validate our parameters
133 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(fromObject),    kQ3Failure);
134 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(toPrivateData), kQ3Failure);
135 
136 
137 
138 	// Copy the data from fromObject to toObject
139 	qd3dStatus = Q3Disk_GetData(fromObject, toInstanceData);
140 
141 	if ( (qd3dStatus == kQ3Success) &&
142 		(toInstanceData->diskAttributeSet != NULL) )
143 	{
144 		dupSet = Q3Object_Duplicate( toInstanceData->diskAttributeSet );
145 		Q3Object_Dispose( toInstanceData->diskAttributeSet );
146 		toInstanceData->diskAttributeSet = dupSet;
147 		if (dupSet == NULL)
148 		{
149 			qd3dStatus = kQ3Failure;
150 		}
151 	}
152 
153 	return(qd3dStatus);
154 }
155 
156 
157 
158 
159 
160 //=============================================================================
161 //      e3geom_disk_calc_point : Compute a point in the disk.
162 //-----------------------------------------------------------------------------
163 static void
164 e3geom_disk_calc_point( const TQ3DiskData *inGeomData, float inSine, float inCosine,
165 	float inRadialScale, TQ3Point3D* outPoint )
166 {
167 	TQ3Vector3D		theVector;
168 
169 	Q3Vector3D_Scale(&inGeomData->majorRadius, inRadialScale * inCosine, &theVector);
170 	Q3Point3D_Vector3D_Add(&inGeomData->origin, &theVector, outPoint);
171 
172 	Q3Vector3D_Scale(&inGeomData->minorRadius, inRadialScale * inSine, &theVector);
173 	Q3Point3D_Vector3D_Add(outPoint, &theVector, outPoint);
174 }
175 
176 
177 
178 
179 
180 //=============================================================================
181 //      e3geom_disk_cache_new : Disk cache new method.
182 //-----------------------------------------------------------------------------
183 static TQ3Object
184 e3geom_disk_cache_new(TQ3ViewObject theView, TQ3GeometryObject theGeom, const TQ3DiskData *geomData)
185 {	float						theAngle, deltaAngle, cosAngle, sinAngle;
186 	TQ3Uns32					numSides, numPoints, numTriangles, n;
187 	TQ3Boolean					isPartAngleRange, hasHoleInCenter;
188 	float						startAngle, endAngle, angleRange;
189 	float						uMin, uMax, vMin, vMax;
190 	TQ3TriMeshAttributeData		vertexAttributes[2];
191 	TQ3Vector3D					surfaceNormalVector;
192 	TQ3SubdivisionStyleData		subdivisionData;
193 	TQ3TriMeshTriangleData		*theTriangles;
194 	TQ3TriMeshData				triMeshData;
195 	TQ3Vector3D					*theNormals;
196 	float						crossLength;
197 	TQ3GeometryObject			theTriMesh;
198 	TQ3Point3D					*thePoints;
199 	TQ3Status					qd3dStatus;
200 	TQ3GroupObject				theGroup;
201 	TQ3Param2D					*theUVs;
202 
203 
204 
205 	// Get the UV limits and make sure they are valid.
206 	// These are for specifying partial disks, and have little to do
207 	// with surface UV coordinates.
208 	uMin  = E3Num_Clamp(geomData->uMin, 0.0f, 1.0f);
209 	uMax  = E3Num_Clamp(geomData->uMax, 0.0f, 1.0f);
210 	vMin  = E3Num_Clamp(geomData->vMin, 0.0f, 1.0f);
211 	vMax  = E3Num_Clamp(geomData->vMax, 0.0f, 1.0f);
212 	// It is possible for uMin to be greater than uMax, so that
213 	// we can specify which way to wrap around the circle.
214 	// But it doesn't make sense for vMin to be greater than vMax.
215 	if (vMin > vMax)
216 		E3Float_Swap( vMin, vMax );
217 	hasHoleInCenter = (vMin > kQ3RealZero)? kQ3True : kQ3False;
218 
219 
220 
221 	// Turn the u limits into an angle range in radians.
222 	startAngle = uMin * kQ32Pi;
223 	endAngle = uMax * kQ32Pi;
224 	if (startAngle > endAngle)
225 		startAngle -= kQ32Pi;
226 	angleRange = endAngle - startAngle;
227 	isPartAngleRange = E3Float_Abs( angleRange - kQ32Pi ) > kQ3RealZero?
228 		kQ3True : kQ3False;
229 
230 
231 
232 	// Get the subdivision style, to figure out how many sides we should have.
233 	numSides   = 10;
234 	qd3dStatus = Q3View_GetSubdivisionStyleState(theView, &subdivisionData);
235 	if (qd3dStatus == kQ3Success)
236 		{
237 		switch (subdivisionData.method) {
238 			case kQ3SubdivisionMethodConstant:
239 				// For a disk, parameter c1 is the number of sides and c2 is unused
240 				numSides = (TQ3Uns32) subdivisionData.c1;
241 				break;
242 
243 			case kQ3SubdivisionMethodWorldSpace:
244 				// keep the length of any side less than or equal to c1
245 				{
246 					TQ3Matrix4x4	localToWorld;
247 					TQ3Vector3D		bigRadius, workVec;
248 
249 					// Find the longer of the two radius vectors.
250 					bigRadius = geomData->majorRadius;
251 					if (Q3Vector3D_LengthSquared( &geomData->majorRadius ) <
252 						Q3Vector3D_LengthSquared( &geomData->minorRadius ) )
253 					{
254 						bigRadius = geomData->minorRadius;
255 					}
256 
257 					// divide the circumference by c1
258 					Q3View_GetLocalToWorldMatrixState( theView, &localToWorld );
259 					Q3Vector3D_Transform( &bigRadius, &localToWorld, &workVec );
260 					numSides = (TQ3Uns32) ((kQ32Pi * Q3Vector3D_Length(&workVec))
261 							/ subdivisionData.c1);
262 				}
263 				break;
264 
265 			case kQ3SubdivisionMethodScreenSpace:
266 				// Not implemented
267 				break;
268 
269 			case kQ3SubdivisionMethodSize32:
270 			default:
271 				Q3_ASSERT(!"Unknown subdivision method");
272 				break;
273 			}
274 		}
275 	numSides  = E3Num_Clamp(numSides, 3, 256);
276 
277 
278 
279 	// For a solid disk, we need one triangle for each side, but if there is a hole
280 	// in the center, we need two triangles for each side.
281 	// If the disk is not on the full angle range, we need extra points for the
282 	// boundary.
283 	if (hasHoleInCenter)
284 	{
285 		numTriangles = numSides * 2;
286 		numPoints = numSides * 2;
287 		if (isPartAngleRange == kQ3True)
288 			numPoints += 2;
289 	}
290 	else	// solid
291 	{
292 		numTriangles = numSides;
293 		numPoints = numSides + 1;	// + 1 for center
294 		if (isPartAngleRange == kQ3True)
295 			numPoints += 1;
296 	}
297 
298 
299 
300 	// Allocate the memory we need for the TriMesh data
301 	thePoints    = (TQ3Point3D *)             Q3Memory_Allocate(numPoints * sizeof(TQ3Point3D));
302 	theNormals   = (TQ3Vector3D *)            Q3Memory_Allocate(numPoints * sizeof(TQ3Vector3D));
303 	theUVs       = (TQ3Param2D  *)            Q3Memory_Allocate(numPoints * sizeof(TQ3Param2D));
304 	theTriangles = (TQ3TriMeshTriangleData *) Q3Memory_Allocate(numTriangles * sizeof(TQ3TriMeshTriangleData));
305 
306 	if (thePoints == NULL || theNormals == NULL || theUVs == NULL || theTriangles == NULL)
307 		{
308 		Q3Memory_Free(&thePoints);
309 		Q3Memory_Free(&theNormals);
310 		Q3Memory_Free(&theUVs);
311 		Q3Memory_Free(&theTriangles);
312 
313 		return(NULL);
314 		}
315 
316 
317 
318 	// Define the sides, as a cosine/sine combination of major and minor radius vectors
319 	deltaAngle = angleRange / (float) numSides;
320 	for (n = 0, theAngle = startAngle; n < numSides; ++n, theAngle += deltaAngle)
321 		{
322 		// Figure out where we are
323 		cosAngle = (float) cos(theAngle);
324 		sinAngle = (float) sin(theAngle);
325 
326 
327 		// Set up the points
328 		if (hasHoleInCenter)
329 			{
330 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMax, &thePoints[2*n] );
331 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMin, &thePoints[2*n+1] );
332 			}
333 		else
334 			{
335 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMax, &thePoints[n] );
336 			}
337 
338 
339 		// Set up the surface UV coordinates
340 		if (hasHoleInCenter)
341 			{
342 			theUVs[2*n].u = (vMax * cosAngle + 1.0f) / 2.0f;
343 			theUVs[2*n].v = (vMax * sinAngle + 1.0f) / 2.0f;
344 			theUVs[2*n+1].u = (vMin * cosAngle + 1.0f) / 2.0f;
345 			theUVs[2*n+1].v = (vMin * sinAngle + 1.0f) / 2.0f;
346 			}
347 		else
348 			{
349 			theUVs[n].u = (vMax * cosAngle + 1.0f) / 2.0f;
350 			theUVs[n].v = (vMax * sinAngle + 1.0f) / 2.0f;
351 			}
352 
353 
354 		// Set up the triangles
355 		if (hasHoleInCenter)
356 			{
357 			if (isPartAngleRange)
358 				{
359 				theTriangles[2*n].pointIndices[0] = 2*n + 1;
360 				theTriangles[2*n].pointIndices[1] = 2*n;
361 				theTriangles[2*n].pointIndices[2] = 2*n + 2;
362 
363 				theTriangles[2*n+1].pointIndices[0] = 2*n + 1;
364 				theTriangles[2*n+1].pointIndices[1] = 2*n + 2;
365 				theTriangles[2*n+1].pointIndices[2] = 2*n + 3;
366 				}
367 			else
368 				{
369 				theTriangles[2*n].pointIndices[0] = 2*n + 1;
370 				theTriangles[2*n].pointIndices[1] = 2*n;
371 				theTriangles[2*n].pointIndices[2] = (2*n + 2) % (2*numSides);
372 
373 				theTriangles[2*n+1].pointIndices[0] = 2*n + 1;
374 				theTriangles[2*n+1].pointIndices[1] = (2*n + 2) % (2*numSides);
375 				theTriangles[2*n+1].pointIndices[2] = (2*n + 3) % (2*numSides);
376 				}
377 			}
378 		else
379 			{
380 			if (isPartAngleRange)
381 				{
382 				theTriangles[n].pointIndices[0] = numSides + 1;
383 				theTriangles[n].pointIndices[1] = n;
384 				theTriangles[n].pointIndices[2] = n + 1;
385 				}
386 			else
387 				{
388 				theTriangles[n].pointIndices[0] = numSides;
389 				theTriangles[n].pointIndices[1] = n;
390 				theTriangles[n].pointIndices[2] = (n + 1) % numSides;
391 				}
392 			}
393 		}
394 
395 
396 
397 	// Finish with center and/or boundary
398 	if (isPartAngleRange)
399 		{
400 		cosAngle = (float) cos(theAngle);
401 		sinAngle = (float) sin(theAngle);
402 		if (hasHoleInCenter)
403 			{
404 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMax,
405 				&thePoints[2*numSides] );
406 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMin,
407 				&thePoints[2*numSides+1] );
408 			theUVs[2*numSides].u = (vMax * cosAngle + 1.0f) / 2.0f;
409 			theUVs[2*numSides].v = (vMax * sinAngle + 1.0f) / 2.0f;
410 			theUVs[2*numSides+1].u = (vMin * cosAngle + 1.0f) / 2.0f;
411 			theUVs[2*numSides+1].v = (vMin * sinAngle + 1.0f) / 2.0f;
412 			}
413 		else
414 			{
415 			e3geom_disk_calc_point( geomData, sinAngle, cosAngle, vMax,
416 				&thePoints[numSides] );
417 			thePoints[numSides+1]  = geomData->origin;
418 			theUVs[numSides].u = (vMax * cosAngle + 1.0f) / 2.0f;
419 			theUVs[numSides].v = (vMax * sinAngle + 1.0f) / 2.0f;
420 			theUVs[numSides+1].u   = 0.5f;
421 			theUVs[numSides+1].v   = 0.5f;
422 			}
423 		}
424 	else
425 		{
426 		if (hasHoleInCenter == kQ3False)
427 			{
428 			thePoints[numSides]  = geomData->origin;
429 			theUVs[numSides].u   = 0.5f;
430 			theUVs[numSides].v   = 0.5f;
431 			}
432 		}
433 
434 
435 
436 	// Surface normal is the cross product of the majorRadius and minorRadius
437 	Q3Vector3D_Cross(&geomData->majorRadius, &geomData->minorRadius, &surfaceNormalVector);
438 	crossLength = Q3Vector3D_Length( &surfaceNormalVector );
439 	if (crossLength <= kQ3RealZero)
440 	{
441 		surfaceNormalVector.x = 1.0f;	// arbitrary
442 		E3ErrorManager_PostError( kQ3ErrorDegenerateGeometry, kQ3False );
443 	}
444 	else
445 	{
446 		Q3Vector3D_Scale( &surfaceNormalVector, 1.0f/crossLength, &surfaceNormalVector );
447 	}
448 
449 	for (n = 0; n < numPoints; ++n)
450 		theNormals[ n ] = surfaceNormalVector;
451 
452 
453 
454 	// Initialise the vertex attributes
455 	vertexAttributes[0].attributeType     = kQ3AttributeTypeNormal;
456 	vertexAttributes[0].data              = theNormals;
457 	vertexAttributes[0].attributeUseArray = NULL;
458 
459 	vertexAttributes[1].attributeType     = kQ3AttributeTypeSurfaceUV;
460 	vertexAttributes[1].data              = theUVs;
461 	vertexAttributes[1].attributeUseArray = NULL;
462 
463 
464 
465 	// Initialise the TriMesh data
466 	triMeshData.numPoints                 = numPoints;
467 	triMeshData.points                    = thePoints;
468 	triMeshData.numTriangles              = numTriangles;
469 	triMeshData.triangles                 = theTriangles;
470 	triMeshData.numTriangleAttributeTypes = 0;
471 	triMeshData.triangleAttributeTypes    = NULL;
472 	triMeshData.numEdges                  = 0;
473 	triMeshData.edges                     = NULL;
474 	triMeshData.numEdgeAttributeTypes     = 0;
475 	triMeshData.edgeAttributeTypes        = NULL;
476 	triMeshData.numVertexAttributeTypes   = 2;
477 	triMeshData.vertexAttributeTypes      = vertexAttributes;
478 	triMeshData.triMeshAttributeSet       = geomData->diskAttributeSet;
479 
480 	Q3BoundingBox_SetFromPoints3D(&triMeshData.bBox, triMeshData.points, triMeshData.numPoints, sizeof(TQ3Point3D));
481 
482 
483 
484 	// Create the TriMesh
485 	theTriMesh = Q3TriMesh_New(&triMeshData);
486 	theGroup   = E3TriMesh_BuildOrientationGroup(theTriMesh, kQ3OrientationStyleCounterClockwise);
487 
488 
489 
490 	// Clean up
491 	Q3Memory_Free(&thePoints);
492 	Q3Memory_Free(&theNormals);
493 	Q3Memory_Free(&theUVs);
494 	Q3Memory_Free(&theTriangles);
495 
496 
497 
498 	// Return the cached geometry
499 	return(theGroup);
500 }
501 
502 
503 
504 
505 
506 
507 //=============================================================================
508 //      e3geom_disk_get_attribute : Disk get attribute set pointer.
509 //-----------------------------------------------------------------------------
510 static TQ3AttributeSet *
511 e3geom_disk_get_attribute ( E3Disk* disk )
512 	{
513 	// Return the address of the geometry attribute set
514 	return & disk->instanceData.diskAttributeSet ;
515 	}
516 
517 
518 
519 
520 
521 //=============================================================================
522 //      e3geom_disk_metahandler : Disk metahandler.
523 //-----------------------------------------------------------------------------
524 static TQ3XFunctionPointer
525 e3geom_disk_metahandler(TQ3XMethodType methodType)
526 {	TQ3XFunctionPointer		theMethod = NULL;
527 
528 
529 
530 	// Return our methods
531 	switch (methodType) {
532 		case kQ3XMethodTypeObjectNew:
533 			theMethod = (TQ3XFunctionPointer) e3geom_disk_new;
534 			break;
535 
536 		case kQ3XMethodTypeObjectDelete:
537 			theMethod = (TQ3XFunctionPointer) e3geom_disk_delete;
538 			break;
539 
540 		case kQ3XMethodTypeObjectDuplicate:
541 			theMethod = (TQ3XFunctionPointer) e3geom_disk_duplicate;
542 			break;
543 
544 		case kQ3XMethodTypeGeomCacheNew:
545 			theMethod = (TQ3XFunctionPointer) e3geom_disk_cache_new;
546 			break;
547 
548 		case kQ3XMethodTypeGeomGetAttribute:
549 			theMethod = (TQ3XFunctionPointer) e3geom_disk_get_attribute;
550 			break;
551 
552 		case kQ3XMethodTypeGeomUsesSubdivision:
553 			theMethod = (TQ3XFunctionPointer) kQ3True;
554 			break;
555 		}
556 
557 	return(theMethod);
558 }
559 
560 
561 
562 
563 
564 //=============================================================================
565 //      Public functions
566 //-----------------------------------------------------------------------------
567 //      E3GeometryDisk_RegisterClass : Register the class.
568 //-----------------------------------------------------------------------------
569 #pragma mark -
570 TQ3Status
571 E3GeometryDisk_RegisterClass(void)
572 	{
573 	// Register the class
574 	return Q3_REGISTER_CLASS (	kQ3ClassNameGeometryDisk,
575 								e3geom_disk_metahandler,
576 								E3Disk ) ;
577 	}
578 
579 
580 
581 
582 
583 //=============================================================================
584 //      E3GeometryDisk_UnregisterClass : Unregister the class.
585 //-----------------------------------------------------------------------------
586 TQ3Status
587 E3GeometryDisk_UnregisterClass(void)
588 {	TQ3Status		qd3dStatus;
589 
590 
591 
592 	// Unregister the class
593 	qd3dStatus = E3ClassTree::UnregisterClass(kQ3GeometryTypeDisk, kQ3True);
594 
595 	return(qd3dStatus);
596 }
597 
598 
599 
600 
601 
602 //=============================================================================
603 //      E3Disk_New : Create a disk object.
604 //-----------------------------------------------------------------------------
605 #pragma mark -
606 TQ3GeometryObject
607 E3Disk_New(const TQ3DiskData *diskData)
608 {
609 	TQ3Object		theObject;
610 
611 
612 	if (diskData == NULL)
613 	{
614 		TQ3DiskData		defaultDiskData = {
615 			{ 0.0f, 0.0f, 0.0f },
616 			{ 1.0f, 0.0f, 0.0f },
617 			{ 0.0f, 1.0f, 0.0f },
618 			0.0f, 1.0f, 0.0f, 1.0f,
619 			NULL
620 		};
621 		theObject = E3ClassTree::CreateInstance ( kQ3GeometryTypeDisk, kQ3False, &defaultDiskData ) ;
622 	}
623 	else
624 		theObject = E3ClassTree::CreateInstance ( kQ3GeometryTypeDisk, kQ3False, diskData ) ;
625 
626 
627 	return (theObject);
628 }
629 
630 
631 
632 
633 
634 //=============================================================================
635 //      E3Disk_Submit : Submit a disk.
636 //-----------------------------------------------------------------------------
637 TQ3Status
638 E3Disk_Submit(const TQ3DiskData *diskData, TQ3ViewObject theView)
639 {	TQ3Status		qd3dStatus;
640 
641 
642 
643 	// Submit the geometry
644 	qd3dStatus = E3View_SubmitImmediate(theView, kQ3GeometryTypeDisk, diskData);
645 	return(qd3dStatus);
646 }
647 
648 
649 
650 
651 
652 //=============================================================================
653 //      E3Disk_SetData : Set the data for a disk object.
654 //-----------------------------------------------------------------------------
655 TQ3Status
656 E3Disk_SetData(TQ3GeometryObject theDisk, const TQ3DiskData *diskData)
657 	{
658 	E3Disk* disk = (E3Disk*) theDisk ;
659 
660 	// Set the data
661 	disk->instanceData.origin      = diskData->origin ;
662 	disk->instanceData.majorRadius = diskData->majorRadius ;
663 	disk->instanceData.minorRadius = diskData->minorRadius ;
664 	disk->instanceData.uMin   	  = diskData->uMin ;
665 	disk->instanceData.uMax   	  = diskData->uMax ;
666 	disk->instanceData.vMin   	  = diskData->vMin ;
667 	disk->instanceData.vMax   	  = diskData->vMax ;
668 
669 	E3Shared_Replace ( &disk->instanceData.diskAttributeSet, diskData->diskAttributeSet ) ;
670 
671 	Q3Shared_Edited ( disk ) ;
672 
673 	return kQ3Success ;
674 	}
675 
676 
677 
678 
679 
680 //=============================================================================
681 //      E3Disk_GetData : Get the data for a disk object.
682 //-----------------------------------------------------------------------------
683 TQ3Status
684 E3Disk_GetData(TQ3GeometryObject theDisk, TQ3DiskData *diskData)
685 	{
686 	E3Disk* disk = (E3Disk*) theDisk ;
687 
688 	// Get the data
689 	diskData->origin      = disk->instanceData.origin ;
690 	diskData->majorRadius = disk->instanceData.majorRadius ;
691 	diskData->minorRadius = disk->instanceData.minorRadius ;
692 	diskData->uMin   	  = disk->instanceData.uMin ;
693 	diskData->uMax   	  = disk->instanceData.uMax ;
694 	diskData->vMin   	  = disk->instanceData.vMin ;
695 	diskData->vMax   	  = disk->instanceData.vMax ;
696 
697 	E3Shared_Acquire ( & diskData->diskAttributeSet, disk->instanceData.diskAttributeSet ) ;
698 
699 	return kQ3Success ;
700 	}
701 
702 
703 
704 
705 
706 //=============================================================================
707 //      E3Disk_EmptyData : Empty the data for a disk object.
708 //-----------------------------------------------------------------------------
709 TQ3Status
710 E3Disk_EmptyData(TQ3DiskData *diskData)
711 {
712 
713 
714 	// Release the data
715 	Q3Object_CleanDispose(&diskData->diskAttributeSet);
716 
717 	return(kQ3Success);
718 }
719 
720 
721 
722 
723 
724 //=============================================================================
725 //      E3Disk_SetOrigin : Set the origin for a disk object.
726 //-----------------------------------------------------------------------------
727 TQ3Status
728 E3Disk_SetOrigin(TQ3GeometryObject theDisk, const TQ3Point3D *origin)
729 	{
730 	E3Disk* disk = (E3Disk*) theDisk ;
731 
732 	// Set the origin
733 	disk->instanceData.origin = *origin ;
734 
735 	Q3Shared_Edited ( disk ) ;
736 
737 	return kQ3Success ;
738 	}
739 
740 
741 
742 
743 
744 //=============================================================================
745 //      E3Disk_SetMajorRadius : Set the major radius for a disk object.
746 //-----------------------------------------------------------------------------
747 TQ3Status
748 E3Disk_SetMajorRadius(TQ3GeometryObject theDisk, const TQ3Vector3D *majorRadius)
749 	{
750 	E3Disk* disk = (E3Disk*) theDisk ;
751 
752 	// Set the major radius
753 	disk->instanceData.majorRadius = *majorRadius ;
754 
755 	Q3Shared_Edited ( disk ) ;
756 
757 	return kQ3Success ;
758 	}
759 
760 
761 
762 
763 
764 //=============================================================================
765 //      E3Disk_SetMinorRadius : Set the minor radius for a disk object.
766 //-----------------------------------------------------------------------------
767 TQ3Status
768 E3Disk_SetMinorRadius(TQ3GeometryObject theDisk, const TQ3Vector3D *minorRadius)
769 	{
770 	E3Disk* disk = (E3Disk*) theDisk ;
771 
772 	// Set the minor radius
773 	disk->instanceData.minorRadius = *minorRadius ;
774 
775 	Q3Shared_Edited ( disk ) ;
776 
777 	return kQ3Success ;
778 	}
779 
780 
781 
782 
783 
784 //=============================================================================
785 //      E3Disk_GetOrigin : Get the origin for a disk object.
786 //-----------------------------------------------------------------------------
787 TQ3Status
788 E3Disk_GetOrigin(TQ3GeometryObject theDisk, TQ3Point3D *origin)
789 	{
790 	E3Disk* disk = (E3Disk*) theDisk ;
791 
792 	// Get the origin
793 	*origin = disk->instanceData.origin;
794 
795 	return kQ3Success ;
796 	}
797 
798 
799 
800 
801 
802 //=============================================================================
803 //      E3Disk_GetMajorRadius : Get the major radius for a disk object.
804 //-----------------------------------------------------------------------------
805 TQ3Status
806 E3Disk_GetMajorRadius(TQ3GeometryObject theDisk, TQ3Vector3D *majorRadius)
807 	{
808 	E3Disk* disk = (E3Disk*) theDisk ;
809 
810 	// Get the major radius
811 	*majorRadius = disk->instanceData.majorRadius ;
812 
813 	return kQ3Success ;
814 	}
815 
816 
817 
818 
819 
820 //=============================================================================
821 //      E3Disk_GetMinorRadius : Get the minor radius for a disk object.
822 //-----------------------------------------------------------------------------
823 TQ3Status
824 E3Disk_GetMinorRadius(TQ3GeometryObject theDisk, TQ3Vector3D *minorRadius)
825 	{
826 	E3Disk* disk = (E3Disk*) theDisk ;
827 
828 	// Get the minor radius
829 	*minorRadius = disk->instanceData.minorRadius ;
830 
831 	return kQ3Success ;
832 	}
833