| 805 | } |
| 806 | |
| 807 | MeshPrimitivePtr MeshPrimitive::createSphere( float radius, float zMin, float zMax, float thetaMax, const Imath::V2i &divisions, const Canceller *canceller ) |
| 808 | { |
| 809 | IntVectorDataPtr vertexIds = new IntVectorData; |
| 810 | IntVectorDataPtr verticesPerFace = new IntVectorData; |
| 811 | std::vector<int> &vpf = verticesPerFace->writable(); |
| 812 | std::vector<int> &vIds = vertexIds->writable(); |
| 813 | |
| 814 | V3fVectorDataPtr pData = new V3fVectorData; |
| 815 | V3fVectorDataPtr nData = new V3fVectorData; |
| 816 | nData->setInterpretation( GeometricData::Normal ); |
| 817 | std::vector<V3f> &pVector = pData->writable(); |
| 818 | std::vector<V3f> &nVector = nData->writable(); |
| 819 | |
| 820 | V2fVectorDataPtr uvData = new V2fVectorData; |
| 821 | uvData->setInterpretation( GeometricData::UV ); |
| 822 | IntVectorDataPtr uvIndicesData = new IntVectorData; |
| 823 | std::vector<Imath::V2f> &uvs = uvData->writable(); |
| 824 | std::vector<int> &uvIndices = uvIndicesData->writable(); |
| 825 | |
| 826 | /// \todo: Rewrite this such that the poles are aligned to Y rather than Z. |
| 827 | /// The centroid should remain at origin, uv(0,0) should be at the south |
| 828 | /// pole (e.g -Y), uv(1,1) should be at the north pole (e.g. +Y). The stable |
| 829 | /// seam (i.e. the edge that doesn't move when theta < 360) should remain |
| 830 | /// aligned to +X with uv(0,0.5), and the moving edge should be uv(1,0.5). |
| 831 | /// Remember to update SpherePrimitive at the same time. |
| 832 | |
| 833 | float oMin = asinf( zMin ); |
| 834 | float oMax = asinf( zMax ); |
| 835 | const unsigned int nO = max( 4u, (unsigned int)round( divisions.x * (oMax - oMin) / M_PI ) + 1 ); |
| 836 | |
| 837 | float thetaMaxRad = thetaMax / 180.0f * M_PI; |
| 838 | const unsigned int nT = max( 7u, (unsigned int)round( divisions.y * thetaMaxRad / (M_PI*2) ) + 1 ); |
| 839 | |
| 840 | for ( unsigned int i=0; i<nO; i++ ) |
| 841 | { |
| 842 | float v = (float)i/(float)(nO-1); |
| 843 | float o = lerp( oMin, oMax, v ); |
| 844 | float z = radius * sinf( o ); |
| 845 | float r = radius * cosf( o ); |
| 846 | |
| 847 | const bool atPole = |
| 848 | ( i == 0 && zMin == -1 ) || |
| 849 | ( i == nO - 1 && zMax == 1 ) |
| 850 | ; |
| 851 | |
| 852 | const int baseVertexId = pVector.size(); |
| 853 | const int baseUVIndex = uvs.size(); |
| 854 | |
| 855 | for ( unsigned int j=0; j<nT; j++ ) |
| 856 | { |
| 857 | Canceller::check( canceller ); |
| 858 | float u = (float)j/(float)(nT-1); |
| 859 | if( atPole ) |
| 860 | { |
| 861 | u += 0.5f / (float)(nT-1); |
| 862 | } |
| 863 | |
| 864 | float theta = thetaMaxRad * u; |