예제 #1
0
TriangleMesh* DebugGeometryBuilder::createTorus( float innerRadius, float outerRadius, const Matrix& transform, int segmentsCount, int segmentVerticesCount )
{
   const Vector& origin = transform.position();
   const Vector& mainAxis = transform.forwardVec();
   const Vector& sideAxis = transform.sideVec();
   Vector circumferenceAxis = transform.upVec();

   FastFloat circumferenceWidth; circumferenceWidth.setFromFloat( outerRadius - innerRadius );
   FastFloat radius; radius.setFromFloat( innerRadius + outerRadius - innerRadius );

   // calculate torus vertices
   const uint verticesCount = segmentsCount * segmentVerticesCount;
   std::vector<LitVertex> vertices( verticesCount );
   {
      FastFloat dMainAngle; dMainAngle.setFromFloat( DEG2RAD( 360.0f / (float)segmentsCount ) );
      FastFloat dSegmentAngle; dSegmentAngle.setFromFloat( DEG2RAD( 360.0f / (float)segmentVerticesCount ) );
      FastFloat mainAngle = Float_0;

      Quaternion mainRot, circumferenceRot;
      Vector vtxPos, posOnCircumference, radiusDisplacement, radiusVec, torusVtx;
      radiusVec.setMul( sideAxis, radius );
      uint vtxIdx = 0;
      for ( uint segmentIdx = 0; segmentIdx < segmentsCount; ++segmentIdx, mainAngle.add( dMainAngle ) )
      {
         mainRot.setAxisAngle( mainAxis, mainAngle );
         mainRot.transform( radiusVec, radiusDisplacement );

         FastFloat segmentAngle = Float_0;
         for ( uint segVtxIdx = 0; segVtxIdx < segmentVerticesCount; ++segVtxIdx, segmentAngle.add( dSegmentAngle ) )
         {
            circumferenceRot.setAxisAngle( circumferenceAxis, segmentAngle );
            Quaternion rotQ;
            rotQ.setMul( circumferenceRot, mainRot );

            // first - create a point on the circumference of the toruses' segment
            vtxPos.setMul( sideAxis, circumferenceWidth );
            rotQ.transform( vtxPos, posOnCircumference );

            // and displace the circumference point so that it ends up in its final position on the toruses' circumference
            torusVtx.setAdd( radiusDisplacement, posOnCircumference );
            torusVtx.add( origin );

            // store the vertex
            torusVtx.store( vertices[vtxIdx].m_coords );
            ++vtxIdx;
         }
      }
   }

   // set torus indices
   const uint outFacesCount = verticesCount * 2;
   std::vector<Face> outFaces( outFacesCount );
   {
      uint faceIdx = 0;
      for ( uint segmentIdx = 0; segmentIdx < segmentsCount; ++segmentIdx )
      {
         uint currSegmentFirstVtx = segmentIdx * segmentVerticesCount;
         uint nextSegmentFirstVtx = ( currSegmentFirstVtx + segmentVerticesCount ) % verticesCount;

         for ( uint segVtxIdx = 0; segVtxIdx < segmentVerticesCount; ++segVtxIdx )
         {
            uint skipOffset = 0;
            if ( segVtxIdx == 0 )
            {
               skipOffset = segmentVerticesCount;
            }

            outFaces[faceIdx].idx[0] = currSegmentFirstVtx + segVtxIdx - 1 + skipOffset;
            outFaces[faceIdx].idx[1] = currSegmentFirstVtx + segVtxIdx;
            outFaces[faceIdx].idx[2] = nextSegmentFirstVtx + segVtxIdx - 1 + skipOffset;
            ++faceIdx;

            outFaces[faceIdx].idx[0] = currSegmentFirstVtx + segVtxIdx;
            outFaces[faceIdx].idx[1] = nextSegmentFirstVtx + segVtxIdx;
            outFaces[faceIdx].idx[2] = nextSegmentFirstVtx + segVtxIdx - 1 + skipOffset;
            ++faceIdx;
         }
      }
   }

   TriangleMesh* mesh = new TriangleMesh( FilePath(), vertices, outFaces );
   return mesh;
}