PXR_NAMESPACE_OPEN_SCOPE /// "Flattens out" the given \p interpolation onto face-vertexes of the given /// \p meshFn, returning a mapping of the face-vertex indices to data indices. /// Takes into account data authored sparsely if \p assignmentIndices and /// \p unauthoredValuesIndex are specified. static MIntArray _GetMayaFaceVertexAssignmentIds( const MFnMesh& meshFn, const TfToken& interpolation, const VtIntArray& assignmentIndices, const int unauthoredValuesIndex) { MIntArray valueIds(meshFn.numFaceVertices(), -1); MItMeshFaceVertex itFV(meshFn.object()); unsigned int fvi = 0; for (itFV.reset(); !itFV.isDone(); itFV.next(), ++fvi) { int valueId = 0; if (interpolation == UsdGeomTokens->constant) { valueId = 0; } else if (interpolation == UsdGeomTokens->uniform) { valueId = itFV.faceId(); } else if (interpolation == UsdGeomTokens->vertex) { valueId = itFV.vertId(); } else if (interpolation == UsdGeomTokens->faceVarying) { valueId = fvi; } if (static_cast<size_t>(valueId) < assignmentIndices.size()) { // The data is indexed, so consult the indices array for the // correct index into the data. valueId = assignmentIndices[valueId]; if (valueId == unauthoredValuesIndex) { // This component had no authored value, so leave it unassigned. continue; } } valueIds[fvi] = valueId; } return valueIds; }
PXR_NAMESPACE_OPEN_SCOPE bool MayaMeshWriter::_GetMeshUVSetData( const MFnMesh& mesh, const MString& uvSetName, VtArray<GfVec2f>* uvArray, TfToken* interpolation, VtArray<int>* assignmentIndices) { MStatus status; // Sanity check first to make sure this UV set even has assigned values // before we attempt to do anything with the data. MIntArray uvCounts, uvIds; status = mesh.getAssignedUVs(uvCounts, uvIds, &uvSetName); if (status != MS::kSuccess) { return false; } if (uvCounts.length() == 0 || uvIds.length() == 0) { return false; } // using itFV.getUV() does not always give us the right answer, so // instead, we have to use itFV.getUVIndex() and use that to index into the // UV set. MFloatArray uArray; MFloatArray vArray; mesh.getUVs(uArray, vArray, &uvSetName); if (uArray.length() != vArray.length()) { return false; } // We'll populate the assignment indices for every face vertex, but we'll // only push values into the data if the face vertex has a value. All face // vertices are initially unassigned/unauthored. const unsigned int numFaceVertices = mesh.numFaceVertices(&status); uvArray->clear(); assignmentIndices->assign((size_t)numFaceVertices, -1); *interpolation = UsdGeomTokens->faceVarying; MItMeshFaceVertex itFV(mesh.object()); unsigned int fvi = 0; for (itFV.reset(); !itFV.isDone(); itFV.next(), ++fvi) { if (!itFV.hasUVs(uvSetName)) { // No UVs for this faceVertex, so leave it unassigned. continue; } int uvIndex; itFV.getUVIndex(uvIndex, &uvSetName); if (uvIndex < 0 || static_cast<size_t>(uvIndex) >= uArray.length()) { return false; } GfVec2f value(uArray[uvIndex], vArray[uvIndex]); uvArray->push_back(value); (*assignmentIndices)[fvi] = uvArray->size() - 1; } PxrUsdMayaUtil::MergeEquivalentIndexedValues(uvArray, assignmentIndices); PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices(mesh, interpolation, assignmentIndices); return true; }
/// Collect values from the color set named \p colorSet. /// If \p isDisplayColor is true and this color set represents displayColor, /// the unauthored/unpainted values in the color set will be filled in using /// the shader values in \p shadersRGBData and \p shadersAlphaData if available. /// Values are gathered per face vertex, but then the data is compressed to /// vertex, uniform, or constant interpolation if possible. /// Unauthored/unpainted values will be given the index -1. bool MayaMeshWriter::_GetMeshColorSetData( MFnMesh& mesh, const MString& colorSet, bool isDisplayColor, const VtArray<GfVec3f>& shadersRGBData, const VtArray<float>& shadersAlphaData, const VtArray<int>& shadersAssignmentIndices, VtArray<GfVec3f>* colorSetRGBData, VtArray<float>* colorSetAlphaData, TfToken* interpolation, VtArray<int>* colorSetAssignmentIndices, MFnMesh::MColorRepresentation* colorSetRep, bool* clamped) { // If there are no colors, return immediately as failure. if (mesh.numColors(colorSet) == 0) { return false; } MColorArray colorSetData; const MColor unsetColor(-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX); if (mesh.getFaceVertexColors(colorSetData, &colorSet, &unsetColor) == MS::kFailure) { return false; } if (colorSetData.length() == 0) { return false; } // Get the color set representation and clamping. *colorSetRep = mesh.getColorRepresentation(colorSet); *clamped = mesh.isColorClamped(colorSet); // We'll populate the assignment indices for every face vertex, but we'll // only push values into the data if the face vertex has a value. All face // vertices are initially unassigned/unauthored. colorSetRGBData->clear(); colorSetAlphaData->clear(); colorSetAssignmentIndices->assign((size_t)colorSetData.length(), -1); *interpolation = UsdGeomTokens->faceVarying; // Loop over every face vertex to populate the value arrays. MItMeshFaceVertex itFV(mesh.object()); unsigned int fvi = 0; for (itFV.reset(); !itFV.isDone(); itFV.next(), ++fvi) { // If this is a displayColor color set, we may need to fallback on the // bound shader colors/alphas for this face in some cases. In // particular, if the color set is alpha-only, we fallback on the // shader values for the color. If the color set is RGB-only, we // fallback on the shader values for alpha only. If there's no authored // color for this face vertex, we use both the color AND alpha values // from the shader. bool useShaderColorFallback = false; bool useShaderAlphaFallback = false; if (isDisplayColor) { if (colorSetData[fvi] == unsetColor) { useShaderColorFallback = true; useShaderAlphaFallback = true; } else if (*colorSetRep == MFnMesh::kAlpha) { // The color set does not provide color, so fallback on shaders. useShaderColorFallback = true; } else if (*colorSetRep == MFnMesh::kRGB) { // The color set does not provide alpha, so fallback on shaders. useShaderAlphaFallback = true; } } // If we're exporting displayColor and we use the value from the color // set, we need to convert it to linear. bool convertDisplayColorToLinear = isDisplayColor; // Shader values for the mesh could be constant // (shadersAssignmentIndices is empty) or uniform. int faceIndex = itFV.faceId(); if (useShaderColorFallback) { // There was no color value in the color set to use, so we use the // shader color, or the default color if there is no shader color. // This color will already be in linear space, so don't convert it // again. convertDisplayColorToLinear = false; int valueIndex = -1; if (shadersAssignmentIndices.empty()) { if (shadersRGBData.size() == 1) { valueIndex = 0; } } else if (faceIndex >= 0 && static_cast<size_t>(faceIndex) < shadersAssignmentIndices.size()) { int tmpIndex = shadersAssignmentIndices[faceIndex]; if (tmpIndex >= 0 && static_cast<size_t>(tmpIndex) < shadersRGBData.size()) { valueIndex = tmpIndex; } } if (valueIndex >= 0) { colorSetData[fvi][0] = shadersRGBData[valueIndex][0]; colorSetData[fvi][1] = shadersRGBData[valueIndex][1]; colorSetData[fvi][2] = shadersRGBData[valueIndex][2]; } else { // No shader color to fallback on. Use the default shader color. colorSetData[fvi][0] = _ShaderDefaultRGB[0]; colorSetData[fvi][1] = _ShaderDefaultRGB[1]; colorSetData[fvi][2] = _ShaderDefaultRGB[2]; } } if (useShaderAlphaFallback) { int valueIndex = -1; if (shadersAssignmentIndices.empty()) { if (shadersAlphaData.size() == 1) { valueIndex = 0; } } else if (faceIndex >= 0 && static_cast<size_t>(faceIndex) < shadersAssignmentIndices.size()) { int tmpIndex = shadersAssignmentIndices[faceIndex]; if (tmpIndex >= 0 && static_cast<size_t>(tmpIndex) < shadersAlphaData.size()) { valueIndex = tmpIndex; } } if (valueIndex >= 0) { colorSetData[fvi][3] = shadersAlphaData[valueIndex]; } else { // No shader alpha to fallback on. Use the default shader alpha. colorSetData[fvi][3] = _ShaderDefaultAlpha; } } // If we have a color/alpha value, add it to the data to be returned. if (colorSetData[fvi] != unsetColor) { GfVec3f rgbValue = _ColorSetDefaultRGB; float alphaValue = _ColorSetDefaultAlpha; if (useShaderColorFallback || (*colorSetRep == MFnMesh::kRGB) || (*colorSetRep == MFnMesh::kRGBA)) { rgbValue = _LinearColorFromColorSet(colorSetData[fvi], convertDisplayColorToLinear); } if (useShaderAlphaFallback || (*colorSetRep == MFnMesh::kAlpha) || (*colorSetRep == MFnMesh::kRGBA)) { alphaValue = colorSetData[fvi][3]; } colorSetRGBData->push_back(rgbValue); colorSetAlphaData->push_back(alphaValue); (*colorSetAssignmentIndices)[fvi] = colorSetRGBData->size() - 1; } } _MergeEquivalentColorSetValues(colorSetRGBData, colorSetAlphaData, colorSetAssignmentIndices); PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices(mesh, interpolation, colorSetAssignmentIndices); return true; }