home *** CD-ROM | disk | FTP | other *** search
/ Ray Dream Studio 5 / Ray Dream.iso / pc / DreamSDK / Windows / SAMPLES / PRIMITIV / SPHR / COMSPHR.CPP next >
Encoding:
C/C++ Source or Header  |  1997-07-11  |  13.7 KB  |  476 lines

  1. // Copyright (c)1995 Ray Dream, Inc. All Rights Reserved.
  2. /* $Id: COMSphr.cpp 1.10 1997/06/20 22:32:28 damien Exp $ */
  3.  
  4. ////////////////////////////////////////////////////////////////////////
  5. //   Geometric Primitive Example : Sphere                             //
  6. //--------------------------------------------------------------------//
  7. //   Implementation of the Sphere Interface                           //
  8. //////////////////////////////////////////////////////////////////////// 
  9.  
  10. #include "math.h"
  11.  
  12. #ifndef __COMSPHR__
  13. #include "COMSPHR.h"
  14. #endif
  15.  
  16. #ifndef __3DCOFAIL__
  17. #include "3DCoFail.h"
  18. #endif
  19.  
  20. // Constante values
  21. NUM3D kDefaultSphereRadius = 3.0;
  22. NUM3D kUmax                = 360.0;
  23. NUM3D kVmax                = 180.0;
  24.  
  25.          
  26. // Functions to create the Patches of the Sphere         
  27. // -- Inverse a Patch
  28. void InversePatch(PATCH3D *aPatch) {
  29.   VECTOR3D swapPoint;
  30.  
  31.   for (short uu=0;uu<=1;uu++) {
  32.     for (short vv=0;vv<4;vv++) {
  33.             for (int i=0; i<3; i++) {
  34.                 swapPoint[i]=aPatch->fVertices[uu][vv][i];
  35.                 aPatch->fVertices[uu][vv][i]=aPatch->fVertices[3-uu][vv][i];
  36.                 aPatch->fVertices[3-uu][vv][i]=swapPoint[i];
  37.                 }
  38.             }
  39.         }
  40.     }
  41.  
  42. // Create Default Patches of the Sphere
  43. void MakeSpherePatch(PATCH3D *aPatch,NUM3D di,NUM3D dj,NUM3D dk) 
  44. {
  45.   NUM3D magicFactor=0.552284749830793398; 
  46.   NUM3D swapUV;
  47.  
  48.   aPatch->fVertices[0][3][0]=0.0;
  49.   aPatch->fVertices[0][3][1]=0.0;
  50.   aPatch->fVertices[0][3][2]=dk;
  51.  
  52.   aPatch->fVertices[0][2][0]=magicFactor*di;
  53.   aPatch->fVertices[0][2][1]=0.0;
  54.   aPatch->fVertices[0][2][2]=dk;
  55.  
  56.   aPatch->fVertices[0][1][0]=di;
  57.   aPatch->fVertices[0][1][1]=0.0;
  58.   aPatch->fVertices[0][1][2]=magicFactor*dk;
  59.  
  60.   aPatch->fVertices[0][0][0]=di;
  61.   aPatch->fVertices[0][0][1]=0.0;
  62.   aPatch->fVertices[0][0][2]=0.0;
  63.  
  64.   aPatch->fVertices[1][0][0]=di;
  65.   aPatch->fVertices[1][0][1]=magicFactor*dj;
  66.   aPatch->fVertices[1][0][2]=0.0;
  67.  
  68.   aPatch->fVertices[2][0][0]=magicFactor*di;
  69.   aPatch->fVertices[2][0][1]=dj;
  70.   aPatch->fVertices[2][0][2]=0.0;
  71.  
  72.   aPatch->fVertices[3][0][0]=0.0;
  73.   aPatch->fVertices[3][0][1]=dj;
  74.   aPatch->fVertices[3][0][2]=0.0;
  75.  
  76.   aPatch->fVertices[3][1][0]=0.0;
  77.   aPatch->fVertices[3][1][1]=dj;
  78.   aPatch->fVertices[3][1][2]=magicFactor*dk;
  79.  
  80.   aPatch->fVertices[3][2][0]=0.0;
  81.   aPatch->fVertices[3][2][1]=magicFactor*dj;
  82.   aPatch->fVertices[3][2][2]=dk;
  83.  
  84.   aPatch->fVertices[3][3][0]=0.0;
  85.   aPatch->fVertices[3][3][1]=0.0;
  86.   aPatch->fVertices[3][3][2]=dk;
  87.  
  88.   aPatch->fVertices[2][3][0]=0.0;
  89.   aPatch->fVertices[2][3][1]=0.0;
  90.   aPatch->fVertices[2][3][2]=dk;
  91.  
  92.   aPatch->fVertices[1][3][0]=0.0;
  93.   aPatch->fVertices[1][3][1]=0.0;
  94.   aPatch->fVertices[1][3][2]=dk;
  95.  
  96.   //middle of the Patch (control points)
  97.   aPatch->fVertices[1][2][0]=magicFactor*di;
  98.   aPatch->fVertices[1][2][1]=magicFactor*magicFactor*dj;
  99.   aPatch->fVertices[1][2][2]=dk;
  100.  
  101.   aPatch->fVertices[2][2][0]=magicFactor*magicFactor*di;
  102.   aPatch->fVertices[2][2][1]=magicFactor*dj;
  103.   aPatch->fVertices[2][2][2]=dk;
  104.  
  105.  
  106.   aPatch->fVertices[1][1][0]=di;
  107.   aPatch->fVertices[1][1][1]=magicFactor*dj;
  108.   aPatch->fVertices[1][1][2]=magicFactor*dk;
  109.  
  110.   aPatch->fVertices[2][1][0]=magicFactor*di;
  111.   aPatch->fVertices[2][1][1]=dj;
  112.   aPatch->fVertices[2][1][2]=magicFactor*dk;
  113.  
  114.   // Patch's uv-space information
  115.   if (di>0.0) 
  116.   {
  117.     if (dj>0.0) 
  118.     {
  119.       aPatch->fu[0]=0.0;  // 0
  120.       aPatch->fu[1]=kUmax/4;        // to 90∞
  121.     }
  122.     else {
  123.       aPatch->fu[0]=(kUmax+kUmax+kUmax)/4;  // 270∞
  124.       aPatch->fu[1]=kUmax;                  // to 360∞
  125.     }
  126.   }
  127.   else 
  128.   {
  129.     if (dj>0.0) 
  130.     {
  131.       aPatch->fu[0]=kUmax/4;  // 90∞
  132.       aPatch->fu[1]=kUmax/2;  // to 180∞
  133.     }
  134.     else 
  135.     {
  136.       aPatch->fu[0]=kUmax/2;                // 180∞
  137.       aPatch->fu[1]=(kUmax+kUmax+kUmax)/4;  // to 270∞
  138.     }
  139.   }
  140.  
  141.   if (dk>0.0) 
  142.   {
  143.     aPatch->fv[0]=kVmax/2;   // 90∞
  144.     aPatch->fv[1]=kVmax;     // to 180∞
  145.   }
  146.   else 
  147.   {
  148.     swapUV=aPatch->fu[0];
  149.     aPatch->fu[0]=aPatch->fu[1];
  150.     aPatch->fu[1]=swapUV;
  151.   
  152.     aPatch->fv[0]=kVmax/2;
  153.     aPatch->fv[1]=0.0;
  154.   }
  155.   
  156.   int signi=(di>0.0?1:-1); 
  157.   int signj=(dj>0.0?1:-1); 
  158.   int signk=(dk>0.0?1:-1); 
  159.   if (signi*signj*signk<0) 
  160.   {
  161.     InversePatch(aPatch);
  162.   }
  163.  
  164.   aPatch->fUVSpace=0;
  165.   aPatch->fReserved=0;
  166. }
  167.  
  168.  
  169. //***********************************************************************
  170.  
  171.  
  172.  
  173. // Constructor / Destructor of the C++ Object :
  174. Sphere::Sphere() {
  175.   fCRef=0; // Reference Counter
  176.   }
  177.   
  178. Sphere::~Sphere() {
  179.   global_count_Obj--; 
  180.   }
  181.   
  182. // IUnknown Interface :
  183. HRESULT Sphere::QueryInterface(THIS_ REFIID riid,LPVOID FAR* ppvObj) {
  184.   *ppvObj=NULL;
  185.   
  186.   // The Sphere knows the interfaces of the parent Objects
  187.   if (IsEqualIID(riid, IID_IUnknown))
  188.     *ppvObj=(IUnknown*)(I3DExGeometricPrimitive*)this;    // this is OK because QueryInterface is only used on PC with C++ and COM
  189.   else if (IsEqualIID(riid, IID_I3DExGeometricPrimitive))
  190.     *ppvObj=(I3DExGeometricPrimitive*)this;
  191.   else if (IsEqualIID(riid, IID_I3DExDataExchanger))
  192.     *ppvObj=(I3DExDataExchanger*)this;
  193.   else if (IsEqualIID(riid, IID_I3DExtension))
  194.     *ppvObj=(I3DExtension*)this;
  195.     
  196.   // we must add reference if we return an interface
  197.   if (*ppvObj!=NULL) {
  198.     ((LPUNKNOWN)*ppvObj)->AddRef();
  199.     return NOERROR;
  200.     }
  201.   else {
  202.     return ResultFromScode(E_NOINTERFACE);
  203.     }
  204.   }
  205.  
  206. ULONG Sphere::AddRef(THIS) {
  207.   return fCRef++;
  208.   }
  209.   
  210. ULONG Sphere::Release(THIS) {
  211.   ULONG UnreleaseObject=fCRef--;
  212.   
  213.   if (fCRef==0)
  214.      delete this; // No reference left, so destroy the object
  215.   
  216.   return UnreleaseObject;
  217.   // local variable used, because fCRef can be destroyed before.
  218.   }
  219.   
  220. // I3DExtension methods :
  221. I3DExtension* Sphere::Clone(THIS) {
  222.   Sphere* theClone = new Sphere;
  223.   if (theClone) {
  224.     theClone->AddRef();
  225.     }                               
  226.   return (I3DExtension*)theClone;
  227.   }   
  228.  
  229. HRESULT Sphere::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
  230.   InitCoFailure(shellUtilities);
  231.   return NOERROR;
  232.   }
  233.  
  234. // I3DExDataExchanger methods :
  235. ExtensionDataMap* Sphere::GetExtensionDataMap(THIS) {
  236.   return NULL;
  237.   }               
  238.   
  239. void* Sphere::GetExtensionDataBuffer(THIS) {
  240.   return NULL;
  241.   }
  242.   
  243. HRESULT Sphere::ExtensionDataChanged(THIS) {
  244.   return NOERROR;
  245.   }
  246.  
  247. HRESULT Sphere::HandleEvent(THIS_ ULONG SourceID) {
  248.   return ResultFromScode(E_NOTIMPL);
  249.   }
  250.  
  251. short Sphere::GetResID(THIS) {
  252.   return -1;  // always return -1, if you do not have a view
  253.               // Here, we have a view to change the number of branches of the Star
  254.   }
  255.   
  256. // I3DExGeometricPrimitive methods
  257. // -- Geometry calls
  258. HRESULT Sphere::EnumPatches(THIS_ EnumPatchesCallback callback, void* privData) {
  259.   PATCH3D aPatch;
  260.  
  261.   MakeSpherePatch(&aPatch,kDefaultSphereRadius,kDefaultSphereRadius,kDefaultSphereRadius);
  262.   callback(&aPatch,privData);
  263.   MakeSpherePatch(&aPatch,-kDefaultSphereRadius,kDefaultSphereRadius,kDefaultSphereRadius);
  264.   callback(&aPatch,privData);
  265.   MakeSpherePatch(&aPatch,kDefaultSphereRadius,-kDefaultSphereRadius,kDefaultSphereRadius);
  266.   callback(&aPatch,privData);
  267.   MakeSpherePatch(&aPatch,-kDefaultSphereRadius,-kDefaultSphereRadius,kDefaultSphereRadius);
  268.   callback(&aPatch,privData);
  269.   MakeSpherePatch(&aPatch,kDefaultSphereRadius,kDefaultSphereRadius,-kDefaultSphereRadius);
  270.   callback(&aPatch,privData);
  271.   MakeSpherePatch(&aPatch,-kDefaultSphereRadius,kDefaultSphereRadius,-kDefaultSphereRadius);
  272.   callback(&aPatch,privData);
  273.   MakeSpherePatch(&aPatch,kDefaultSphereRadius,-kDefaultSphereRadius,-kDefaultSphereRadius);
  274.   callback(&aPatch,privData);
  275.   MakeSpherePatch(&aPatch,-kDefaultSphereRadius,-kDefaultSphereRadius,-kDefaultSphereRadius);
  276.   callback(&aPatch,privData);
  277.  
  278.   return NOERROR;
  279.   }
  280.   
  281. HRESULT Sphere::EnumFacets(THIS_ EnumFacetsCallback callback, void* privData, NUM3D fidelity) {
  282.   return ResultFromScode(E_NOTIMPL);
  283.   }              
  284.  
  285. HRESULT Sphere::GetNbrLOD(short &nbrLod) {
  286.   return ResultFromScode(E_NOTIMPL);
  287.     }
  288.  
  289. HRESULT Sphere::GetLOD(short lodIndex, NUM3D &lod) {
  290.   return ResultFromScode(E_NOTIMPL);
  291.     }
  292.  
  293. HRESULT Sphere::MakeFacetMesh(short index, FacetMesh &amesh) {
  294.   return ResultFromScode(E_NOTIMPL);
  295.     }
  296.  
  297. HRESULT Sphere::MakeFacetMesh(NUM3D lod, FacetMesh &amesh) {
  298.   return ResultFromScode(E_NOTIMPL);
  299.     }
  300.                       
  301. // Give the boundary Box
  302. HRESULT Sphere::GetBBox(THIS_ BOX3D* bbox) 
  303. { bbox->fMin[0]=-kDefaultSphereRadius;
  304.   bbox->fMax[0]=kDefaultSphereRadius;
  305.   bbox->fMin[1]=-kDefaultSphereRadius;
  306.   bbox->fMax[1]=kDefaultSphereRadius;
  307.   bbox->fMin[2]=-kDefaultSphereRadius;
  308.   bbox->fMax[2]=kDefaultSphereRadius;
  309.   return NOERROR;
  310. }
  311.   
  312. // -- Shading calls
  313. ULONG Sphere::GetUVSpaceCount(THIS) 
  314. {
  315.   return 1; // the Sphere is describe with only 1 UV-Space
  316. }
  317.  
  318. HRESULT Sphere::GetUVSpace(THIS_ ULONG uvSpaceID, UVSpaceInfo* uvSpaceInfo) 
  319. {
  320.   if (uvSpaceID == 0)
  321.   { 
  322.     // UV-Space is equivalent to Spherical Coordinates
  323.     uvSpaceInfo->fMin[0] = 0.0;       // u coordinate goes from 0 to 360
  324.     uvSpaceInfo->fMax[0] = kUmax;
  325.     uvSpaceInfo->fMin[1] = 0.0;       // v coordinate goes from 0 to 180
  326.     uvSpaceInfo->fMax[1] = kVmax; 
  327.     
  328.     uvSpaceInfo->fWraparound[0] = TRUE; 
  329.     uvSpaceInfo->fWraparound[1] = FALSE;
  330.    // uvSpaceInfo->fIsFlatSurface = FALSE;  // the surface is not flat
  331.   }
  332.   return NOERROR;
  333. }
  334.   
  335. // We use the default interpolation method to get all the coordinate of a point in UV Coordinates
  336. HRESULT Sphere::UV2XYZ(THIS_ VECTOR2D* uv,ULONG uvSpaceID, VECTOR3D* resultPosition, BOOLEAN* inUVSpace) {
  337.   NUM3D phi,theta;
  338.   NUM3D sinphi,cosphi;
  339.   NUM3D sintheta,costheta;
  340.  
  341.   *inUVSpace=TRUE;
  342.   if (((*uv)[0]<0.0) || ((*uv)[0]>=kUmax)) *inUVSpace=FALSE;
  343.   if (((*uv)[1]<0.0) || ((*uv)[1]>=kVmax)) *inUVSpace=FALSE;
  344.  
  345.   if (*inUVSpace==TRUE)
  346.   {
  347.     phi=(*uv)[0];
  348.     theta=(*uv)[1]-(kVmax/2);
  349.   
  350.     // Spherical Coordinates To XYZ-Coordinates
  351.     sinphi=sin(phi);
  352.         cosphi=cos(phi); //phi.DegreeGetSinCos(sinphi,cosphi);
  353.     sintheta=sin(theta);
  354.         costheta=cos(theta); //theta.DegreeGetSinCos(sintheta,costheta);
  355.   
  356.     (*resultPosition)[0]=cosphi*costheta;
  357.     (*resultPosition)[1]=sinphi*costheta;
  358.     (*resultPosition)[2]=sintheta;
  359.     (*resultPosition)[0] *= kDefaultSphereRadius;
  360.     (*resultPosition)[1] *= kDefaultSphereRadius;
  361.     (*resultPosition)[2] *= kDefaultSphereRadius;
  362.   }
  363.   
  364.   return NOERROR;
  365. }
  366.  
  367. // -- Ray Tracing calls
  368. HRESULT Sphere::RayHit(THIS_ BOOLEAN* didHit, Ray3D* aR, RayHitParameters* RayHitParams, RayHit3D* hit) 
  369.   VECTOR3D OriginToCenter;
  370.   NUM3D    DirectionNorm2;
  371.   NUM3D    dotProduct;
  372.   NUM3D    t;              // Sphere Center = Ray Origin + t * Ray Direction
  373.   VECTOR3D CH;             // position of the center projected on the ray
  374.   NUM3D    distCH2;        // square of the distance of the projected point
  375.   NUM3D    resT;
  376.   NUM3D    delta,delta2;
  377.   NUM3D    radius2=kDefaultSphereRadius*kDefaultSphereRadius;
  378.  
  379.   OriginToCenter[0]=-aR->fOrigin[0];
  380.   OriginToCenter[1]=-aR->fOrigin[1];
  381.   OriginToCenter[2]=-aR->fOrigin[2];
  382.  
  383.   DirectionNorm2=aR->fDirection[0]*aR->fDirection[0] +
  384.                    aR->fDirection[1]*aR->fDirection[1] +
  385.                                  aR->fDirection[2]*aR->fDirection[2];
  386.   dotProduct    =aR->fDirection[0]*OriginToCenter[0] + 
  387.                      aR->fDirection[1]*OriginToCenter[1] + 
  388.                                  aR->fDirection[2]*OriginToCenter[2];
  389.   t=dotProduct/DirectionNorm2;
  390.  
  391.   CH[0]=aR->fOrigin[0]+aR->fDirection[0]*t;
  392.     CH[1]=aR->fOrigin[1]+aR->fDirection[1]*t;
  393.     CH[2]=aR->fOrigin[2]+aR->fDirection[2]*t;
  394.   distCH2=SQR(CH[0]) + SQR(CH[1]) + SQR(CH[2]);
  395.   if (distCH2>radius2) { 
  396.     *didHit=FALSE;
  397.     }
  398.   else if (distCH2==radius2) {
  399.     resT=t;
  400.     *didHit=TRUE;
  401.     }
  402.   else { // distCH2<radius2 
  403.     *didHit=TRUE;
  404.     delta2=(radius2-distCH2)/DirectionNorm2;
  405.     delta=sqrt(delta2); //delta2.GetSquareRoot(delta);
  406.     resT=t-delta;
  407.     if (resT<=RayHitParams->tmin) {
  408.       resT=t+delta;
  409.       }
  410.     }
  411.   if (resT<=RayHitParams->tmin) { 
  412.         *didHit=FALSE;
  413.     }
  414.  
  415.   if (resT>RayHitParams->tmax) { 
  416.         *didHit=FALSE;
  417.     }
  418.    
  419.   if (*didHit==TRUE) {
  420.         hit->fPosition[0]=aR->fOrigin[0]+aR->fDirection[0]*resT;
  421.         hit->fPosition[1]=aR->fOrigin[1]+aR->fDirection[1]*resT;
  422.         hit->fPosition[2]=aR->fOrigin[2]+aR->fDirection[2]*resT;
  423.         hit->fNormal[0]=hit->fPosition[0]/kDefaultSphereRadius;
  424.         hit->fNormal[1]=hit->fPosition[1]/kDefaultSphereRadius;
  425.         hit->fNormal[2]=hit->fPosition[2]/kDefaultSphereRadius;
  426.     hit->ft=resT;
  427.         GetDetails(hit);
  428.     }
  429.  
  430.   return NOERROR;
  431. }
  432.   
  433. void Sphere::GetDetails(RayHit3D* hit) {
  434.     NUM3D phi,theta,rxy;
  435.   NUM3D sinphi,cosphi,sintheta,costheta;
  436.  
  437.     if (!hit->fShouldSetUV && !hit->fShouldSetIsoUV) return;
  438.   
  439.     phi=atan2(hit->fNormal[1],hit->fNormal[0]); //phi.DegreeSetFromSinCos(hit->fNormal[1],hit->fNormal[0]);
  440.   rxy=hit->fNormal[0]*hit->fNormal[0]+hit->fNormal[1]*hit->fNormal[1];
  441.   rxy=sqrt(rxy); //rxy.GetSquareRoot(rxy);
  442.   theta=atan2(hit->fNormal[2],rxy); //theta.DegreeSetFromSinCos(hit->fNormal[2],rxy);
  443.  
  444.   if (hit->fShouldSetUV) {
  445.         hit->fUV[0]=phi;
  446.     if (theta>kVmax) {
  447.             theta = theta - (kVmax*2);
  448.             }
  449.     hit->fUV[1]=theta+(kVmax/2);
  450.         }
  451.   if (hit->fShouldSetIsoUV) {
  452.     sinphi=sin(phi);
  453.         cosphi=cos(phi); //phi.DegreeGetSinCos(sinphi,cosphi);
  454.     sintheta=sin(theta);
  455.         costheta=cos(theta); //theta.DegreeGetSinCos(sintheta,costheta);
  456.     
  457.     hit->fIsoU[0]=-sinphi*kDefaultSphereRadius;
  458.     hit->fIsoU[1]=cosphi*kDefaultSphereRadius;
  459.     hit->fIsoV[2]=0.0;
  460.     hit->fIsoV[0]=cosphi*sintheta*kDefaultSphereRadius;
  461.     hit->fIsoV[1]=sinphi*sintheta*kDefaultSphereRadius;
  462.     hit->fIsoV[2]=costheta*kDefaultSphereRadius;
  463.         }
  464.   
  465.     }
  466.  
  467. HRESULT Sphere::GetRayHitDetails(RayHit3D* hit) {
  468.   return ResultFromScode(E_NOTIMPL);
  469.   }
  470.   
  471. HRESULT Sphere::RayAllHits(THIS_ Ray3D* aR, NUM3D tmin, NUM3D tmax, RayHit3D* hit, RayHitCallback callback, void* privData) {
  472.   return ResultFromScode(E_NOTIMPL);
  473.   }
  474.   
  475.