1 /* NAME: 2 E3GeometryTorus.c 3 4 DESCRIPTION: 5 Implementation of Quesa Torus 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 "E3GeometryTriMesh.h" 50 #include "E3GeometryTorus.h" 51 52 53 54 55 56 //============================================================================= 57 // Internal types 58 //----------------------------------------------------------------------------- 59 60 class E3Torus : 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 ( kQ3GeometryTypeTorus, E3Torus, E3Geometry ) 66 public : 67 68 TQ3TorusData instanceData ; 69 70 } ; 71 72 73 74 //============================================================================= 75 // Internal functions 76 //----------------------------------------------------------------------------- 77 // e3geom_torus_copydata : Copy TQ3TorusData from one to another. 78 //----------------------------------------------------------------------------- 79 // Note : If isDuplicate is true, we duplicate shared objects rather than 80 // obtaining new references to them. 81 //----------------------------------------------------------------------------- 82 static TQ3Status 83 e3geom_torus_copydata(const TQ3TorusData *src, TQ3TorusData *dst, TQ3Boolean isDuplicate) 84 { 85 TQ3Status qd3dStatus = kQ3Success; 86 87 // copy raw data 88 const TQ3Uns32 theSize = sizeof(TQ3Point3D) // origin 89 + 3*sizeof(TQ3Vector3D) // orientation, major & minor axes 90 + 5*sizeof(float) // ratio, u/v min/max 91 + sizeof(TQ3EndCap); // endcaps 92 Q3Memory_Copy( src, dst, theSize ); 93 94 // copy or shared-replace the attributes 95 if (isDuplicate) 96 { 97 if (src->interiorAttributeSet != NULL) 98 { 99 dst->interiorAttributeSet = Q3Object_Duplicate(src->interiorAttributeSet); 100 if (dst->interiorAttributeSet == NULL) qd3dStatus = kQ3Failure; 101 } else dst->interiorAttributeSet = NULL; 102 103 if (src->torusAttributeSet != NULL) 104 { 105 dst->torusAttributeSet = Q3Object_Duplicate(src->torusAttributeSet); 106 if (dst->torusAttributeSet == NULL) qd3dStatus = kQ3Failure; 107 } else dst->torusAttributeSet = NULL; 108 } 109 else { 110 E3Shared_Replace(&dst->interiorAttributeSet, src->interiorAttributeSet); 111 E3Shared_Replace(&dst->torusAttributeSet, src->torusAttributeSet); 112 } 113 114 return qd3dStatus; 115 } 116 117 118 119 120 121 //============================================================================= 122 // e3geom_torus_disposedata : Dispose of a TQ3TorusData. 123 //----------------------------------------------------------------------------- 124 static void 125 e3geom_torus_disposedata(TQ3TorusData *theTorus) 126 { 127 Q3Object_CleanDispose(&theTorus->interiorAttributeSet ); 128 Q3Object_CleanDispose(&theTorus->torusAttributeSet ); 129 } 130 131 132 133 134 135 //============================================================================= 136 // e3geom_torus_new : Torus new method. 137 //----------------------------------------------------------------------------- 138 static TQ3Status 139 e3geom_torus_new(TQ3Object theObject, void *privateData, const void *paramData) 140 { 141 TQ3TorusData *instanceData = (TQ3TorusData *) privateData; 142 const TQ3TorusData *torusData = (const TQ3TorusData *) paramData; 143 TQ3Status qd3dStatus; 144 #pragma unused(theObject) 145 146 qd3dStatus = e3geom_torus_copydata(torusData, instanceData, kQ3False); 147 148 return(qd3dStatus); 149 } 150 151 152 153 154 155 //============================================================================= 156 // e3geom_torus_delete : Torus delete method. 157 //----------------------------------------------------------------------------- 158 static void 159 e3geom_torus_delete(TQ3Object theObject, void *privateData) 160 { TQ3TorusData *instanceData = (TQ3TorusData *) privateData; 161 #pragma unused(theObject) 162 163 // Dispose of our instance data 164 e3geom_torus_disposedata(instanceData); 165 } 166 167 168 169 170 171 //============================================================================= 172 // e3geom_torus_duplicate : Torus duplicate method. 173 //----------------------------------------------------------------------------- 174 static TQ3Status 175 e3geom_torus_duplicate(TQ3Object fromObject, const void *fromPrivateData, 176 TQ3Object toObject, void *toPrivateData) 177 { const TQ3TorusData *fromInstanceData = (const TQ3TorusData *) fromPrivateData; 178 TQ3TorusData *toInstanceData = (TQ3TorusData *) toPrivateData; 179 TQ3Status qd3dStatus; 180 #pragma unused(fromObject) 181 #pragma unused(toObject) 182 183 184 185 // Validate our parameters 186 Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(fromObject), kQ3Failure); 187 Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(fromPrivateData), kQ3Failure); 188 Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(toObject), kQ3Failure); 189 Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(toPrivateData), kQ3Failure); 190 191 192 193 // Initialise the instance data of the new object 194 qd3dStatus = e3geom_torus_copydata( fromInstanceData, toInstanceData, kQ3True ); 195 196 // Handle failure 197 if (qd3dStatus != kQ3Success) 198 e3geom_torus_disposedata(toInstanceData); 199 200 return(qd3dStatus); 201 } 202 203 204 205 206 207 //============================================================================= 208 // e3geom_torus_cache_new : Torus cache new method. 209 //----------------------------------------------------------------------------- 210 // Note : For a definition of the torus geometry, with helpful diagrams, 211 // see: 212 // 213 // http://developer.apple.com/techpubs/quicktime/qtdevdocs/ 214 // QD3D/qd3dgeometry.34.htm 215 //----------------------------------------------------------------------------- 216 static TQ3Object 217 e3geom_torus_cache_new(TQ3ViewObject theView, TQ3GeometryObject theGeom, const TQ3TorusData *geomData) 218 { TQ3TriMeshData triMeshData; 219 TQ3GeometryObject theTriMesh; 220 TQ3GroupObject theGroup; 221 TQ3Uns32 u,v; 222 float uang=0.0f, duang, vang, dvang; 223 TQ3Point3D *points; 224 TQ3Vector3D *normals; 225 float uDiff, vDiff; 226 float uMin, uMax, vMin, vMax; 227 TQ3Param2D *uvs; 228 TQ3TriMeshTriangleData *triangles; 229 TQ3Vector3D vec, axis; // (just temporaries used for intermediate results) 230 TQ3Point3D center; 231 TQ3Uns32 upts=16; // how many points we have around the torus the long way 232 TQ3Uns32 vpts=8; // how many points around one elliptical cross-section 233 TQ3Uns32 pnum = 0, tnum = 0; 234 TQ3Uns32 numpoints, numtriangles; 235 TQ3SubdivisionStyleData subdivisionData; 236 TQ3TriMeshAttributeData vertexAttributes[2]; 237 float sinUAngle, cosUAngle, sinVAngle, cosVAngle; 238 float orientLength, axisLength, ratioTimesOrient, axisDotAxisPrime; 239 TQ3Vector3D majXMinor; 240 TQ3Vector3D axisXOrient, axisPrime, axisPrimeXOrient; 241 TQ3Boolean isRightHanded; 242 243 244 // Get the subdivision style, to figure out how many sides we should have. 245 if (Q3View_GetSubdivisionStyleState( theView, &subdivisionData ) == kQ3Success) { 246 switch (subdivisionData.method) { 247 case kQ3SubdivisionMethodConstant: 248 // upts and vpts are given directly 249 upts = (TQ3Uns32) subdivisionData.c1; 250 vpts = (TQ3Uns32) subdivisionData.c2; 251 break; 252 253 case kQ3SubdivisionMethodWorldSpace: 254 { 255 TQ3Matrix4x4 localToWorld; 256 float majorLen, minorLen, orientLen; 257 258 // Find the lengths of the vectors, in world space. 259 Q3View_GetLocalToWorldMatrixState( theView, &localToWorld ); 260 Q3Vector3D_Transform( &geomData->majorRadius, &localToWorld, &vec ); 261 majorLen = Q3Vector3D_Length( &vec ); 262 Q3Vector3D_Transform( &geomData->minorRadius, &localToWorld, &vec ); 263 minorLen = Q3Vector3D_Length( &vec ); 264 Q3Vector3D_Transform( &geomData->orientation, &localToWorld, &vec ); 265 orientLen = Q3Vector3D_Length( &vec ); 266 267 // keep the length of any side less than or equal to c1; 268 // so divide the circumference by c1 269 upts = (TQ3Uns32) (kQ32Pi * ( E3Num_Max(majorLen, minorLen) + 270 orientLen * geomData->ratio ) / subdivisionData.c1); 271 // similarly for vpts and c1, but this time use the circumference 272 // around a single section of the torus 273 vpts = (TQ3Uns32) (kQ32Pi * orientLen * E3Num_Max(geomData->ratio, 1.0f) 274 / subdivisionData.c1); 275 } 276 break; 277 278 case kQ3SubdivisionMethodScreenSpace: 279 // Not implemented 280 break; 281 282 case kQ3SubdivisionMethodSize32: 283 default: 284 Q3_ASSERT(!"Unknown subdivision method"); 285 break; 286 } 287 288 // sanity checking -- important in case the user screws up the subdivisionData 289 if (upts < 3) upts = 3; 290 if (vpts < 3) vpts = 3; 291 } 292 293 // In order to have proper uv parameterization we need an extra set of vertices 294 // for the closing triangle (since it is not easy to convince any renderer to 295 // have multiple uvs for a vertex) 296 // 297 numpoints = (upts + 1) * (vpts + 1); 298 numtriangles = upts * vpts * 2; 299 300 301 302 // Get the UV limits 303 uMin = E3Num_Clamp(geomData->vMin, 0.0f, 1.0f); 304 uMax = E3Num_Clamp(geomData->uMax, 0.0f, 1.0f); 305 vMin = E3Num_Clamp(geomData->vMin, 0.0f, 1.0f); 306 vMax = E3Num_Clamp(geomData->vMax, 0.0f, 1.0f); 307 uDiff = uMax - uMin; 308 vDiff = vMax - vMin; 309 310 311 // Allocate some memory for the TriMesh 312 points = (TQ3Point3D *) Q3Memory_Allocate( numpoints * sizeof(TQ3Point3D) ); 313 normals = (TQ3Vector3D *) Q3Memory_Allocate( numpoints * sizeof(TQ3Vector3D) ); 314 uvs = (TQ3Param2D *) Q3Memory_Allocate( numpoints * sizeof(TQ3Param2D)); 315 triangles = (TQ3TriMeshTriangleData*) Q3Memory_Allocate( numtriangles * sizeof(TQ3TriMeshTriangleData) ); 316 317 if (points == NULL || normals == NULL || uvs == NULL || triangles == NULL) 318 { 319 Q3Memory_Free(&points); 320 Q3Memory_Free(&normals); 321 Q3Memory_Free(&uvs); 322 Q3Memory_Free(&triangles); 323 324 return(NULL); 325 } 326 327 // The torus has a parametric equation 328 // f(u,v) = origin + axis(u) + cos(v) orientation + 329 // (sin(v) * ratio * |orientation| / |axis(u)|) axis(u) 330 // where 331 // axis(u) = cos(u) majorRadius + sin(u) minorRadius . 332 // The parameter u goes from 0 to 2pi the long way around the torus, and 333 // the parameter v goes from 0 to 2pi the short way. 334 // One can compute a normal vector as the cross product of the partial 335 // derivatives, but the math gets pretty ugly. 336 337 orientLength = Q3Vector3D_Length(&geomData->orientation); 338 ratioTimesOrient = orientLength * geomData->ratio; 339 Q3Vector3D_Cross( &geomData->majorRadius, &geomData->minorRadius, &majXMinor ); 340 341 // Right or left handed? 342 if (Q3Vector3D_Dot( &majXMinor, &geomData->orientation ) > 0.0) 343 { 344 isRightHanded = kQ3True; 345 } 346 else 347 { 348 isRightHanded = kQ3False; 349 } 350 351 // first create the points... 352 duang = kQ32Pi / (float) upts; 353 dvang = kQ32Pi / (float) vpts; 354 for (u=0; u<=upts; u++) { 355 sinUAngle = (float)sin(uang); 356 cosUAngle = (float)cos(uang); 357 358 // for a given u, find the center... 359 Q3Vector3D_Scale( &geomData->majorRadius, cosUAngle, &vec ); 360 Q3Point3D_Vector3D_Add( &geomData->origin, &vec, ¢er ); 361 Q3Vector3D_Scale( &geomData->minorRadius, sinUAngle, &vec ); 362 Q3Point3D_Vector3D_Add( ¢er, &vec, ¢er ); 363 364 // "axis" is the vector from the origin to the center 365 Q3Point3D_Subtract( ¢er, &geomData->origin, &axis ); 366 axisLength = Q3Vector3D_Length(&axis); 367 368 Q3Vector3D_Cross( &axis, &geomData->orientation, &axisXOrient ); 369 // Axis is a function of u. Compute its derivative. 370 Q3Vector3D_Scale( &geomData->majorRadius, - sinUAngle, &axisPrime ); 371 Q3Vector3D_Scale( &geomData->minorRadius, cosUAngle, &vec ); 372 Q3Vector3D_Add( &axisPrime, &vec, &axisPrime ); 373 // We will also need the cross product of axisPrime and orientation, 374 // and the dot product of axis and axisPrime. 375 Q3Vector3D_Cross( &axisPrime, &geomData->orientation, &axisPrimeXOrient ); 376 axisDotAxisPrime = Q3Vector3D_Dot( &axis, &axisPrime ); 377 378 // now, iterate v around the center point 379 380 vang = 0.0f; 381 for (v=0; v<=vpts; v++) { 382 sinVAngle = (float)sin(vang); 383 cosVAngle = (float)cos(vang); 384 385 Q3Vector3D_Scale( &geomData->orientation, cosVAngle, &vec ); 386 Q3Point3D_Vector3D_Add( ¢er, &vec, &points[pnum] ); 387 Q3Vector3D_Scale( &axis, sinVAngle * ratioTimesOrient / axisLength, &vec ); 388 Q3Point3D_Vector3D_Add( &points[pnum], &vec, &points[pnum] ); 389 390 // Compute normal 391 Q3Vector3D_Scale( &axisPrimeXOrient, - sinVAngle * axisLength * 392 (axisLength + sinVAngle * ratioTimesOrient), &normals[pnum] ); 393 Q3Vector3D_Scale( &axisXOrient, sinVAngle * sinVAngle * 394 ratioTimesOrient * axisDotAxisPrime / axisLength, &vec ); 395 Q3Vector3D_Add( &normals[pnum], &vec, &normals[pnum] ); 396 Q3Vector3D_Scale( &majXMinor, - cosVAngle * ratioTimesOrient * 397 (axisLength + sinVAngle * ratioTimesOrient), &vec ); 398 Q3Vector3D_Add( &normals[pnum], &vec, &normals[pnum] ); 399 if (isRightHanded == kQ3True) 400 Q3Vector3D_Negate( &normals[pnum], &normals[pnum] ); 401 402 // uvs come from the surface parameterisation 403 uvs[pnum].u = uMin + (((uDiff / (float) upts)) * u); 404 uvs[pnum].v = vMin + (((vDiff / (float) vpts)) * v); 405 406 // bump the v coordinate to get the same mapping as QD3D: we want to 407 // reverse the texture in v and start it from the center of the ring 408 uvs[pnum].v += (vDiff / 4.0f); 409 uvs[pnum].v = -uvs[pnum].v; 410 411 pnum++; 412 vang += dvang; 413 } 414 uang += duang; 415 } 416 417 418 419 // then, create the triangles 420 pnum = 0; 421 for (u=0; u<upts; u++) { 422 for (v=0; v<vpts; v++) { 423 triangles[tnum].pointIndices[0] = pnum + v; 424 triangles[tnum].pointIndices[1] = pnum + v + 1; 425 triangles[tnum].pointIndices[2] = pnum + vpts + 1 + v; 426 tnum++; 427 triangles[tnum].pointIndices[0] = pnum + v + 1; 428 triangles[tnum].pointIndices[1] = pnum + vpts + 1 + v + 1; 429 triangles[tnum].pointIndices[2] = pnum + vpts + 1 + v; 430 tnum++; 431 } 432 pnum += (vpts + 1); 433 } 434 435 436 437 // set up the attributes (may be a combination of torus & face attributes) 438 E3AttributeSet_Combine( geomData->torusAttributeSet, NULL, 439 &triMeshData.triMeshAttributeSet ); 440 441 // set up remaining trimesh data 442 vertexAttributes[0].attributeType = kQ3AttributeTypeNormal; 443 vertexAttributes[0].data = normals; 444 vertexAttributes[0].attributeUseArray = NULL; 445 446 vertexAttributes[1].attributeType = kQ3AttributeTypeSurfaceUV; 447 vertexAttributes[1].data = uvs; 448 vertexAttributes[1].attributeUseArray = NULL; 449 450 triMeshData.numPoints = numpoints; 451 triMeshData.points = points; 452 triMeshData.numTriangles = numtriangles; 453 triMeshData.triangles = triangles; 454 triMeshData.numTriangleAttributeTypes = 0; 455 triMeshData.triangleAttributeTypes = NULL; 456 triMeshData.numEdges = 0; 457 triMeshData.edges = NULL; 458 triMeshData.numEdgeAttributeTypes = 0; 459 triMeshData.edgeAttributeTypes = NULL; 460 triMeshData.numVertexAttributeTypes = 2; 461 triMeshData.vertexAttributeTypes = vertexAttributes; 462 463 Q3BoundingBox_SetFromPoints3D(&triMeshData.bBox, 464 triMeshData.points, 465 numpoints, 466 sizeof(TQ3Point3D)); 467 468 469 470 // Create the TriMesh 471 theTriMesh = Q3TriMesh_New(&triMeshData); 472 theGroup = E3TriMesh_BuildOrientationGroup(theTriMesh, kQ3OrientationStyleCounterClockwise); 473 474 475 476 // Clean up 477 Q3Object_CleanDispose(&triMeshData.triMeshAttributeSet); 478 Q3Memory_Free(&points); 479 Q3Memory_Free(&normals); 480 Q3Memory_Free(&uvs); 481 Q3Memory_Free(&triangles); 482 483 return(theGroup); 484 } 485 486 487 488 489 490 //============================================================================= 491 // e3geom_torus_get_attribute : Torus get attribute set pointer. 492 //----------------------------------------------------------------------------- 493 static TQ3AttributeSet * 494 e3geom_torus_get_attribute ( E3Torus* torus ) 495 { 496 // Return the address of the geometry attribute set 497 return & torus->instanceData.torusAttributeSet ; 498 } 499 500 501 502 503 504 //============================================================================= 505 // e3geom_torus_metahandler : Torus metahandler. 506 //----------------------------------------------------------------------------- 507 static TQ3XFunctionPointer 508 e3geom_torus_metahandler(TQ3XMethodType methodType) 509 { TQ3XFunctionPointer theMethod = NULL; 510 511 512 513 // Return our methods 514 switch (methodType) { 515 case kQ3XMethodTypeObjectNew: 516 theMethod = (TQ3XFunctionPointer) e3geom_torus_new; 517 break; 518 519 case kQ3XMethodTypeObjectDelete: 520 theMethod = (TQ3XFunctionPointer) e3geom_torus_delete; 521 break; 522 523 case kQ3XMethodTypeObjectDuplicate: 524 theMethod = (TQ3XFunctionPointer) e3geom_torus_duplicate; 525 break; 526 527 case kQ3XMethodTypeGeomCacheNew: 528 theMethod = (TQ3XFunctionPointer) e3geom_torus_cache_new; 529 break; 530 531 case kQ3XMethodTypeGeomGetAttribute: 532 theMethod = (TQ3XFunctionPointer) e3geom_torus_get_attribute; 533 break; 534 535 case kQ3XMethodTypeGeomUsesSubdivision: 536 theMethod = (TQ3XFunctionPointer) kQ3True; 537 break; 538 } 539 540 return(theMethod); 541 } 542 543 544 545 546 547 //============================================================================= 548 // Public functions 549 //----------------------------------------------------------------------------- 550 // E3GeometryTorus_RegisterClass : Register the class. 551 //----------------------------------------------------------------------------- 552 #pragma mark - 553 TQ3Status 554 E3GeometryTorus_RegisterClass(void) 555 { 556 // Register the class 557 return Q3_REGISTER_CLASS ( kQ3ClassNameGeometryTorus, 558 e3geom_torus_metahandler, 559 E3Torus ) ; 560 } 561 562 563 564 565 566 //============================================================================= 567 // E3GeometryTorus_UnregisterClass : Unregister the class. 568 //----------------------------------------------------------------------------- 569 TQ3Status 570 E3GeometryTorus_UnregisterClass(void) 571 { TQ3Status qd3dStatus; 572 573 574 575 // Unregister the class 576 qd3dStatus = E3ClassTree::UnregisterClass(kQ3GeometryTypeTorus, kQ3True); 577 578 return(qd3dStatus); 579 } 580 581 582 583 584 585 //============================================================================= 586 // E3Torus_New : Create a torus object. 587 //----------------------------------------------------------------------------- 588 #pragma mark - 589 TQ3GeometryObject 590 E3Torus_New(const TQ3TorusData *torusData) 591 { TQ3Object theObject; 592 593 594 if (torusData == NULL) 595 { 596 TQ3TorusData defaultTorus = { 597 { 0.0f, 0.0f, 0.0f }, 598 { 1.0f, 0.0f, 0.0f }, 599 { 0.0f, 1.0f, 0.0f }, 600 { 0.0f, 0.0f, 1.0f }, 601 1.0f, 602 0.0f, 1.0f, 0.0f, 1.0f, 603 kQ3EndCapNone, 604 NULL, NULL 605 }; 606 theObject = E3ClassTree::CreateInstance ( kQ3GeometryTypeTorus, kQ3False, &defaultTorus); 607 } 608 else 609 { 610 theObject = E3ClassTree::CreateInstance ( kQ3GeometryTypeTorus, kQ3False, torusData); 611 } 612 613 614 return(theObject); 615 } 616 617 618 619 620 621 //============================================================================= 622 // E3Torus_Submit : Submit a torus. 623 //----------------------------------------------------------------------------- 624 TQ3Status 625 E3Torus_Submit(const TQ3TorusData *torusData, TQ3ViewObject theView) 626 { TQ3Status qd3dStatus; 627 628 629 630 // Submit the geometry 631 qd3dStatus = E3View_SubmitImmediate(theView, kQ3GeometryTypeTorus, torusData); 632 return(qd3dStatus); 633 } 634 635 636 637 638 639 //============================================================================= 640 // E3Torus_SetData : One-line description of the method. 641 //----------------------------------------------------------------------------- 642 TQ3Status 643 E3Torus_SetData(TQ3GeometryObject theTorus, const TQ3TorusData *torusData) 644 { 645 E3Torus* torus = (E3Torus*) theTorus ; 646 647 // first, free the old data 648 e3geom_torus_disposedata ( & torus->instanceData ) ; 649 650 // then copy in the new data 651 TQ3Status qd3dStatus = e3geom_torus_copydata ( torusData, & torus->instanceData, kQ3False ) ; 652 653 Q3Shared_Edited ( torus ) ; 654 655 return qd3dStatus ; 656 } 657 658 659 660 661 662 //============================================================================= 663 // E3Torus_GetData : Get a copy of the torus's internal data. 664 //----------------------------------------------------------------------------- 665 TQ3Status 666 E3Torus_GetData(TQ3GeometryObject theTorus, TQ3TorusData *torusData) 667 { 668 E3Torus* torus = (E3Torus*) theTorus ; 669 670 // Copy the data out of the Torus 671 torusData->interiorAttributeSet = NULL ; 672 torusData->torusAttributeSet = NULL ; 673 674 return e3geom_torus_copydata ( & torus->instanceData, torusData, kQ3False ) ; 675 } 676 677 678 679 680 681 //============================================================================= 682 // E3Torus_SetOrigin : Set the torus origin. 683 //----------------------------------------------------------------------------- 684 TQ3Status 685 E3Torus_SetOrigin(TQ3GeometryObject theTorus, const TQ3Point3D *origin) 686 { 687 E3Torus* torus = (E3Torus*) theTorus ; 688 689 Q3Memory_Copy ( origin, & torus->instanceData.origin, sizeof(TQ3Point3D) ) ; 690 691 Q3Shared_Edited ( torus ) ; 692 693 return kQ3Success ; 694 } 695 696 697 698 699 700 //============================================================================= 701 // E3Torus_SetOrientation : Set the torus orientation. 702 //----------------------------------------------------------------------------- 703 TQ3Status 704 E3Torus_SetOrientation(TQ3GeometryObject theTorus, const TQ3Vector3D *orientation) 705 { 706 E3Torus* torus = (E3Torus*) theTorus ; 707 708 Q3Memory_Copy( orientation, & torus->instanceData.orientation, sizeof(TQ3Vector3D) ); 709 710 Q3Shared_Edited ( torus ) ; 711 712 return kQ3Success ; 713 } 714 715 716 717 718 719 //============================================================================= 720 // E3Torus_SetMajorRadius : Set the torus major radius. 721 //----------------------------------------------------------------------------- 722 TQ3Status 723 E3Torus_SetMajorRadius(TQ3GeometryObject theTorus, const TQ3Vector3D *majorRadius) 724 { 725 E3Torus* torus = (E3Torus*) theTorus ; 726 727 Q3Memory_Copy ( majorRadius, & torus->instanceData.majorRadius, sizeof(TQ3Vector3D) ) ; 728 729 Q3Shared_Edited ( torus ) ; 730 731 return kQ3Success ; 732 } 733 734 735 736 737 738 //============================================================================= 739 // E3Torus_SetMinorRadius : Set the torus minor radius. 740 //----------------------------------------------------------------------------- 741 TQ3Status 742 E3Torus_SetMinorRadius(TQ3GeometryObject theTorus, const TQ3Vector3D *minorRadius) 743 { 744 E3Torus* torus = (E3Torus*) theTorus ; 745 746 Q3Memory_Copy ( minorRadius, & torus->instanceData.minorRadius, sizeof(TQ3Vector3D) ) ; 747 748 Q3Shared_Edited ( torus ) ; 749 750 return kQ3Success ; 751 } 752 753 754 755 756 757 //============================================================================= 758 // E3Torus_GetOrigin : Get the torus's origin. 759 //----------------------------------------------------------------------------- 760 TQ3Status 761 E3Torus_GetOrigin(TQ3GeometryObject theTorus, TQ3Point3D *origin) 762 { 763 Q3Memory_Copy ( & ( (E3Torus*) theTorus )->instanceData.origin, origin, sizeof(TQ3Point3D) ) ; 764 return kQ3Success ; 765 } 766 767 768 769 770 771 //============================================================================= 772 // E3Torus_GetOrientation : Get the torus orientation. 773 //----------------------------------------------------------------------------- 774 TQ3Status 775 E3Torus_GetOrientation(TQ3GeometryObject theTorus, TQ3Vector3D *orientation) 776 { 777 Q3Memory_Copy ( & ( (E3Torus*) theTorus )->instanceData.orientation, orientation, sizeof(TQ3Vector3D) ) ; 778 return kQ3Success ; 779 } 780 781 782 783 784 785 //============================================================================= 786 // E3Torus_GetMajorRadius : Get the torus's major radius. 787 //----------------------------------------------------------------------------- 788 TQ3Status 789 E3Torus_GetMajorRadius(TQ3GeometryObject theTorus, TQ3Vector3D *majorRadius) 790 { 791 Q3Memory_Copy ( & ( (E3Torus*) theTorus )->instanceData.majorRadius, majorRadius, sizeof(TQ3Vector3D) ) ; 792 return kQ3Success ; 793 } 794 795 796 797 798 799 //============================================================================= 800 // E3Torus_GetMinorRadius : Get the torus's minor radius. 801 //----------------------------------------------------------------------------- 802 TQ3Status 803 E3Torus_GetMinorRadius(TQ3GeometryObject theTorus, TQ3Vector3D *minorRadius) 804 { 805 Q3Memory_Copy ( & ( (E3Torus*) theTorus )->instanceData.minorRadius, minorRadius, sizeof(TQ3Vector3D) ) ; 806 return kQ3Success ; 807 } 808 809 810 811 //============================================================================= 812 // E3Torus_GetRatio : Get the torus ratio. 813 //----------------------------------------------------------------------------- 814 TQ3Status 815 E3Torus_SetRatio(TQ3GeometryObject theTorus, float ratio) 816 { 817 E3Torus* torus = (E3Torus*) theTorus ; 818 819 torus->instanceData.ratio = ratio ; 820 821 Q3Shared_Edited ( torus ) ; 822 823 return kQ3Success ; 824 } 825 826 827 //============================================================================= 828 // E3Torus_GetRatio : Get the torus ratio. 829 //----------------------------------------------------------------------------- 830 TQ3Status 831 E3Torus_GetRatio(TQ3GeometryObject theTorus, float *ratio) 832 { 833 *ratio = ( (E3Torus*) theTorus )->instanceData.ratio ; 834 return kQ3Success ; 835 } 836 837 838 839 840 841 842 //============================================================================= 843 // E3Torus_EmptyData : Empty the data for a Torus object. 844 //----------------------------------------------------------------------------- 845 TQ3Status 846 E3Torus_EmptyData(TQ3TorusData *torusData) 847 { 848 849 // Dispose of the data 850 e3geom_torus_disposedata(torusData); 851 852 return(kQ3Success); 853 } 854 855