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; }