diff --git a/CMakeLists.txt b/CMakeLists.txt index 398bb85a5f..dbdc901810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,6 +231,11 @@ if(BUILD_HDSB_PLUGIN) endif() endif() +#------------------------------------------------------------------------------ +# scripts +#------------------------------------------------------------------------------ +add_subdirectory(scripts) + #------------------------------------------------------------------------------ # install #------------------------------------------------------------------------------ diff --git a/lib/mayaHydra/mayaPlugin/plugin.cpp b/lib/mayaHydra/mayaPlugin/plugin.cpp index c1a10b222b..6551e2fa33 100644 --- a/lib/mayaHydra/mayaPlugin/plugin.cpp +++ b/lib/mayaHydra/mayaPlugin/plugin.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -46,13 +47,6 @@ using namespace MayaHydra; -// Don't use smart pointers in the static vector: when Maya is doing its -// default "quick exit" that does not uninitialize plugins, the atexit -// destruction of the overrides in the vector will crash on destruction, -// because Hydra has already destroyed structures these rely on. Simply leak -// the render overrides in this case. -static std::vector gsRenderOverrides; - #if defined(MAYAHYDRA_VERSION) #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -62,6 +56,20 @@ static std::vector gsRenderOverrides; #define PLUGIN_VERSION "Maya-Hydra experimental" #endif +namespace { + const std::string kMayaHydraPluginName = "mayaHydra"; + const std::string kMayaUsdPluginName = "mayaUsdPlugin"; + + // Don't use smart pointers in the static vector: when Maya is doing its + // default "quick exit" that does not uninitialize plugins, the atexit + // destruction of the overrides in the vector will crash on destruction, + // because Hydra has already destroyed structures these rely on. Simply leak + // the render overrides in this case. + std::vector _renderOverrides; + + std::vector _pluginLoadingCallbackIds; +} + void initialize() { Fvp::InitializationParams fvpInitParams; @@ -83,6 +91,35 @@ void finalize() MayaHydra::MayaColorPreferencesTranslator::deleteInstance(); } +void afterPluginLoadCallback( const MStringArray& strs, void* clientData ) +{ + for (const auto& str : strs) { + // If MayaUSD is being loaded, set up our GeomSubsets picking mode UI. + // This will re-create the "Select" menu callback if it has been previously torn down. + if (str.asChar() == kMayaUsdPluginName) { + MGlobal::executeCommand("if (`exists mayaHydra_GeomSubsetsPickMode_SetupUI`) { mayaHydra_GeomSubsetsPickMode_SetupUI; }"); + break; + } + } +} + +void beforePluginUnloadCallback( const MStringArray& strs, void* clientData ) +{ + for (const auto& str : strs) { + // If MayaUSD is being unloaded, tear down our GeomSubsets picking mode UI. + // This resets the variables used to keep track of the UI elements' existence, + // and allows us to recreate them if MayaUSD is reloaded. + // We also do the same if mayaHydra is about to be unloaded : we can't rely on + // the deletion procedure registered through registerUI, as it seems the global + // variables tracking our UI elements have been reset at that point for some reason. + auto strChar = str.asChar(); + if (strChar == kMayaUsdPluginName || strChar == kMayaHydraPluginName) { + MGlobal::executeCommand("mayaHydra_GeomSubsetsPickMode_TeardownUI"); + break; + } + } +} + PLUGIN_EXPORT MStatus initializePlugin(MObject obj) { MString experimental("mayaHydra is experimental."); @@ -118,11 +155,54 @@ PLUGIN_EXPORT MStatus initializePlugin(MObject obj) auto mtohRenderer = std::make_unique(desc); MStatus status = renderer->registerOverride(mtohRenderer.get()); if (status == MS::kSuccess) { - gsRenderOverrides.push_back(mtohRenderer.release()); + _renderOverrides.push_back(mtohRenderer.release()); } } } + if (!plugin.registerUIStrings(nullptr, "mayaHydra_registerUIStrings")) { + ret = MS::kFailure; + ret.perror("Error registering mayaHydra UI string resources."); + return ret; + } + + if (!plugin.registerUI( + "mayaHydra_registerUI_load", + "mayaHydra_registerUI_unload", + "mayaHydra_registerUI_batch_load", + "mayaHydra_registerUI_batch_unload")) + { + ret = MS::kFailure; + ret.perror("Error registering mayaHydra UI procedures."); + return ret; + } + + auto registerPluginLoadingCallback = [&](MSceneMessage::Message pluginLoadingMessage, MMessage::MStringArrayFunction callback) { + MStatus callbackStatus; + MCallbackId callbackId = MSceneMessage::addStringArrayCallback( + pluginLoadingMessage, + callback, + nullptr, + &callbackStatus); + if (callbackStatus) { + _pluginLoadingCallbackIds.push_back(callbackId); + } else { + ret = MS::kFailure; + ret.perror("Error registering mayaHydra plugin loading callback."); + } + }; + + std::vector> pluginLoadingCallbacks = { + {MSceneMessage::Message::kAfterPluginLoad, afterPluginLoadCallback}, + {MSceneMessage::Message::kBeforePluginUnload, beforePluginUnloadCallback} + }; + for (const auto& pluginLoadingCallback : pluginLoadingCallbacks) { + registerPluginLoadingCallback(pluginLoadingCallback.first, pluginLoadingCallback.second); + if (!ret) { + return ret; + } + } + initialize(); return ret; @@ -132,19 +212,23 @@ PLUGIN_EXPORT MStatus uninitializePlugin(MObject obj) { finalize(); + for (const auto& callbackId : _pluginLoadingCallbackIds) { + MSceneMessage::removeCallback(callbackId); + } + MFnPlugin plugin(obj, "Autodesk", PLUGIN_VERSION, "Any"); MStatus ret = MS::kSuccess; if (auto* renderer = MHWRender::MRenderer::theRenderer()) { - for (unsigned int i = 0; i < gsRenderOverrides.size(); i++) { - renderer->deregisterOverride(gsRenderOverrides[i]); - delete gsRenderOverrides[i]; + for (unsigned int i = 0; i < _renderOverrides.size(); i++) { + renderer->deregisterOverride(_renderOverrides[i]); + delete _renderOverrides[i]; } } - gsRenderOverrides.clear(); + _renderOverrides.clear(); // Clear any registered callbacks - MGlobal::executeCommand("callbacks -cc mayaHydra;"); + MGlobal::executeCommand("callbacks -cc -owner mayaHydra;"); if (!plugin.deregisterCommand(MtohViewCmd::name)) { ret = MS::kFailure; diff --git a/lib/mayaHydra/mayaPlugin/renderOverride.cpp b/lib/mayaHydra/mayaPlugin/renderOverride.cpp index 53315d9aa1..8ad3e020eb 100644 --- a/lib/mayaHydra/mayaPlugin/renderOverride.cpp +++ b/lib/mayaHydra/mayaPlugin/renderOverride.cpp @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -255,14 +256,27 @@ UsdPointInstancesPickMode GetPointInstancesPickMode() return pickMode; } +TfToken GetGeomSubsetsPickMode() +{ + static const MString kOptionVarName(MayaHydraPickOptionVars->GeomSubsetsPickMode.GetText()); + + if (MGlobal::optionVarExists(kOptionVarName)) { + return TfToken(MGlobal::optionVarStringValue(kOptionVarName).asChar()); + } + + return GeomSubsetsPickModeTokens->None; +} + struct PickInput { PickInput( const HdxPickHit& pickHitArg, - const MHWRender::MSelectionInfo& pickInfoArg - ) : pickHit(pickHitArg), pickInfo(pickInfoArg) {} + const MHWRender::MSelectionInfo& pickInfoArg, + const bool isSolePickHit + ) : pickHit(pickHitArg), pickInfo(pickInfoArg), isSolePickHit(isSolePickHit) {} const HdxPickHit& pickHit; const MHWRender::MSelectionInfo& pickInfo; + const bool isSolePickHit; }; // Picking output can go either to the UFE representation of the Maya selection @@ -450,15 +464,54 @@ class UsdPickHandler : public MtohRenderOverride::PickHandlerBase { UsdPickHandler(MtohRenderOverride& renderOverride) : PickHandlerBase(renderOverride) {} + +#if PXR_VERSION >= 2403 + std::vector resolveGeomSubsetsPicking( + HdSceneIndexBaseConstRefPtr sceneIndex, + const SdfPath& basePrimPath, + const TfToken& geomSubsetType, + int componentIndex) const + { + if (componentIndex < 0 || sceneIndex->GetPrim(basePrimPath).primType != HdPrimTypeTokens->mesh) { + return {}; + } + + std::vector pickedGeomSubsets; + auto childPaths = sceneIndex->GetChildPrimPaths(basePrimPath); + for (const auto& childPath : childPaths) { + HdSceneIndexPrim childPrim = sceneIndex->GetPrim(childPath); + if (childPrim.primType != HdPrimTypeTokens->geomSubset) { + continue; + } + + HdGeomSubsetSchema geomSubsetSchema = HdGeomSubsetSchema(childPrim.dataSource); + if (!geomSubsetSchema.IsDefined() || geomSubsetSchema.GetType()->GetTypedValue(0) != geomSubsetType) { + continue; + } + + auto geomSubsetIndices = geomSubsetSchema.GetIndices()->GetTypedValue(0); + for (const auto& index : geomSubsetIndices) { + if (index == componentIndex) { + HdPrimOriginSchema primOriginSchema = HdPrimOriginSchema::GetFromParent(childPrim.dataSource); + if (primOriginSchema.IsDefined()) { + auto usdPath = primOriginSchema.GetOriginPath(HdPrimOriginSchemaTokens->scenePath); + pickedGeomSubsets.push_back({usdPath, -1}); + } + } + } + } + return pickedGeomSubsets; + } +#endif // Return the closest path and the instance index in the scene index scene // that corresponds to the pick hit. If the pick hit is not an instance, // the instance index will be -1. - HitPath hitPath(const HdxPickHit& hit) const { - auto primOrigin = HdxPrimOriginInfo::FromPickHit( - renderIndex(), hit); + HitPath resolveInstancePicking(HdRenderIndex& renderIndex, const HdxPickHit& pickHit) const + { + auto primOrigin = HdxPrimOriginInfo::FromPickHit(&renderIndex, pickHit); - if (hit.instancerId.IsEmpty()) { + if (pickHit.instancerId.IsEmpty()) { return {primOrigin.GetFullPath(), -1}; } @@ -487,7 +540,7 @@ class UsdPickHandler : public MtohRenderOverride::PickHandlerBase { // Retrieve pick mode from mayaUsd optionVar, to see if we're picking // instances, the instancer itself, or the prototype instanced by the // point instance. - return pickFn[GetPointInstancesPickMode()](primOrigin, hit); + return pickFn[GetPointInstancesPickMode()](primOrigin, pickHit); } bool handlePickHit( @@ -510,56 +563,82 @@ class UsdPickHandler : public MtohRenderOverride::PickHandlerBase { return false; } - // For the USD pick handler pick results are directly returned with USD - // scene paths, so no need to remove scene index plugin path prefix. - const auto& [pickedUsdPath, instanceNdx] = hitPath(pickInput.pickHit); - - const auto pickedMayaPath = usdPathToUfePath(registration, pickedUsdPath); - const auto snMayaPath = - // As per https://stackoverflow.com/questions/46114214 - // structured bindings cannot be captured by a lambda in C++ 17, - // so pass in pickedUsdPath and instanceNdx as lambda arguments. - [&pickedMayaPath, ®istration]( - const SdfPath& pickedUsdPath, int instanceNdx) { - - if (instanceNdx >= 0) { - // Point instance: add the instance index to the path. - // Appending a numeric component to the path to identify a - // point instance cannot be done on the picked SdfPath, as - // numeric path components are not allowed by SdfPath. Do so - // here with Ufe::Path, which has no such restriction. - return pickedMayaPath + std::to_string(instanceNdx); + std::vector hitPaths; + +#if PXR_VERSION >= 2403 + if (GetGeomSubsetsPickMode() == GeomSubsetsPickModeTokens->Faces) { + auto geomSubsetsHitPaths = resolveGeomSubsetsPicking( + renderIndex()->GetTerminalSceneIndex(), + pickInput.pickHit.objectId, + HdGeomSubsetSchemaTokens->typeFaceSet, + pickInput.pickHit.elementIndex); + if (!geomSubsetsHitPaths.empty()) { + hitPaths.insert(hitPaths.end(), geomSubsetsHitPaths.begin(), geomSubsetsHitPaths.end()); } - // Not an instance: adjust picked path for selection kind. - auto snKind = GetSelectionKind(); - if (snKind.IsEmpty()) { - return pickedMayaPath; + // If we did not find any geomSubset and this is the only pick hit, then fallback to selecting the base prim/instance. + if (hitPaths.empty() && pickInput.isSolePickHit) { + hitPaths.push_back(resolveInstancePicking(*renderIndex(), pickInput.pickHit)); } + } else { + hitPaths.push_back(resolveInstancePicking(*renderIndex(), pickInput.pickHit)); + } +#else + hitPaths.push_back(resolveInstancePicking(*renderIndex(), pickInput.pickHit)); +#endif - // Get the prim from the stage and path, to access the - // UsdModelAPI for the prim. - auto proxyShapeObj = registration->dagNode.object(); - if (proxyShapeObj.isNull()) { - TF_FATAL_ERROR("No mayaUsd proxy shape object corresponds to USD pick"); - return pickedMayaPath; - } + size_t nbSelectedUfeItems = 0; + for (const auto& [pickedUsdPath, instanceNdx] : hitPaths) { + // For the USD pick handler pick results are directly returned with USD + // scene paths, so no need to remove scene index plugin path prefix. + const auto pickedMayaPath = usdPathToUfePath(registration, pickedUsdPath); + const auto snMayaPath = + // As per https://stackoverflow.com/questions/46114214 + // structured bindings cannot be captured by a lambda in C++ 17, + // so pass in pickedUsdPath and instanceNdx as lambda arguments. + [&pickedMayaPath, ®istration]( + const SdfPath& pickedUsdPath, int instanceNdx) { + + if (instanceNdx >= 0) { + // Point instance: add the instance index to the path. + // Appending a numeric component to the path to identify a + // point instance cannot be done on the picked SdfPath, as + // numeric path components are not allowed by SdfPath. Do so + // here with Ufe::Path, which has no such restriction. + return pickedMayaPath + std::to_string(instanceNdx); + } - MayaUsdAPI::ProxyStage proxyStage{proxyShapeObj}; - auto prim = proxyStage.getUsdStage()->GetPrimAtPath(pickedUsdPath); - prim = GetPrimOrAncestorWithKind(prim, snKind); - const auto usdPath = prim ? prim.GetPath() : pickedUsdPath; + // Not an instance: adjust picked path for selection kind. + auto snKind = GetSelectionKind(); + if (snKind.IsEmpty()) { + return pickedMayaPath; + } - return usdPathToUfePath(registration, usdPath); - }(pickedUsdPath, instanceNdx); + // Get the prim from the stage and path, to access the + // UsdModelAPI for the prim. + auto proxyShapeObj = registration->dagNode.object(); + if (proxyShapeObj.isNull()) { + TF_FATAL_ERROR("No mayaUsd proxy shape object corresponds to USD pick"); + return pickedMayaPath; + } - auto si = Ufe::Hierarchy::createItem(snMayaPath); - if (!si) { - return false; - } + MayaUsdAPI::ProxyStage proxyStage{proxyShapeObj}; + auto prim = proxyStage.getUsdStage()->GetPrimAtPath(pickedUsdPath); + prim = GetPrimOrAncestorWithKind(prim, snKind); + const auto usdPath = prim ? prim.GetPath() : pickedUsdPath; - pickOutput.ufeSelection->append(si); - return true; + return usdPathToUfePath(registration, usdPath); + }(pickedUsdPath, instanceNdx); + + auto si = Ufe::Hierarchy::createItem(snMayaPath); + if (!si) { + continue; + } + + pickOutput.ufeSelection->append(si); + nbSelectedUfeItems++; + } + return nbSelectedUfeItems > 0; } }; @@ -1715,7 +1794,7 @@ void MtohRenderOverride::_PopulateSelectionList( MStatus status; for (const HdxPickHit& hit : hits) { - PickInput pickInput(hit, selectInfo); + PickInput pickInput(hit, selectInfo, hits.size() == 1u); auto pickHandler = _PickHandler(hit); if (!hiliteListIsEmpty && _IsMayaPickHandler(pickHandler)){ // Maya does not create Hydra instances, so if the pick hit instancer @@ -1751,6 +1830,8 @@ void MtohRenderOverride::_PickByRegion( HdxPickHitVector& outHits, const MMatrix& viewMatrix, const MMatrix& projMatrix, + bool singlePick, + const TfToken& geomSubsetsPickMode, bool pointSnappingActive, int view_x, int view_y, @@ -1781,9 +1862,17 @@ void MtohRenderOverride::_PickByRegion( HdxPickTaskContextParams pickParams; // Use the same size as selection region is enough to get all pick results. pickParams.resolution.Set(sel_w, sel_h); + pickParams.pickTarget = HdxPickTokens->pickPrimsAndInstances; + pickParams.resolveMode = singlePick ? HdxPickTokens->resolveNearestToCenter : HdxPickTokens->resolveUnique; + pickParams.doUnpickablesOcclude = false; pickParams.viewMatrix.Set(viewMatrix.matrix); pickParams.projectionMatrix.Set(adjustedProjMatrix.matrix); - pickParams.resolveMode = HdxPickTokens->resolveUnique; + pickParams.collection = _renderCollection; + pickParams.outHits = &outHits; + + if (geomSubsetsPickMode == GeomSubsetsPickModeTokens->Faces) { + pickParams.pickTarget = HdxPickTokens->pickFaces; + } if (pointSnappingActive) { pickParams.pickTarget = HdxPickTokens->pickPoints; @@ -1792,11 +1881,6 @@ void MtohRenderOverride::_PickByRegion( pickParams.collection = _pointSnappingCollection; pickParams.collection.SetExcludePaths(_selectionSceneIndex->GetFullySelectedPaths()); } - else { - pickParams.collection = _renderCollection; - } - - pickParams.outHits = &outHits; // Execute picking tasks. HdTaskSharedPtrVector pickingTasks = _taskController->GetPickingTasks(); @@ -1850,6 +1934,8 @@ bool MtohRenderOverride::select( return false; HdxPickHitVector outHits; + const bool singlePick = selectInfo.singleSelection(); + const TfToken geomSubsetsPickMode = GetGeomSubsetsPickMode(); const bool pointSnappingActive = selectInfo.pointSnapping(); if (pointSnappingActive) { @@ -1870,7 +1956,7 @@ bool MtohRenderOverride::select( unsigned int curr_sel_x = cursor_x > (int)curr_sel_w / 2 ? cursor_x - (int)curr_sel_w / 2 : 0; unsigned int curr_sel_y = cursor_y > (int)curr_sel_h / 2 ? cursor_y - (int)curr_sel_h / 2 : 0; - _PickByRegion(outHits, viewMatrix, projMatrix, pointSnappingActive, + _PickByRegion(outHits, viewMatrix, projMatrix, singlePick, geomSubsetsPickMode, pointSnappingActive, view_x, view_y, view_w, view_h, curr_sel_x, curr_sel_y, curr_sel_w, curr_sel_h); // Increase the size of picking region. @@ -1881,7 +1967,7 @@ bool MtohRenderOverride::select( // Pick from original region directly when point snapping is not active or no hit is found yet. if (outHits.empty()) { - _PickByRegion(outHits, viewMatrix, projMatrix, pointSnappingActive, + _PickByRegion(outHits, viewMatrix, projMatrix, singlePick, geomSubsetsPickMode, pointSnappingActive, view_x, view_y, view_w, view_h, sel_x, sel_y, sel_w, sel_h); } diff --git a/lib/mayaHydra/mayaPlugin/renderOverride.h b/lib/mayaHydra/mayaPlugin/renderOverride.h index 76c19d7e74..eec9e2ca7a 100644 --- a/lib/mayaHydra/mayaPlugin/renderOverride.h +++ b/lib/mayaHydra/mayaPlugin/renderOverride.h @@ -169,6 +169,8 @@ class MtohRenderOverride : public MHWRender::MRenderOverride HdxPickHitVector& outHits, const MMatrix& viewMatrix, const MMatrix& projMatrix, + bool singlePick, + const TfToken& geomSubsetsPickMode, bool pointSnappingActive, int view_x, int view_y, diff --git a/lib/mayaHydra/mayaPlugin/tokens.cpp b/lib/mayaHydra/mayaPlugin/tokens.cpp index 4cc78edb95..7d9215d40e 100644 --- a/lib/mayaHydra/mayaPlugin/tokens.cpp +++ b/lib/mayaHydra/mayaPlugin/tokens.cpp @@ -25,4 +25,8 @@ TF_DEFINE_PUBLIC_TOKENS( ); // clang-format on +TF_DEFINE_PUBLIC_TOKENS(MayaHydraPickOptionVars, MAYAHYDRA_PICK_OPTIONVAR_TOKENS); + +TF_DEFINE_PUBLIC_TOKENS(GeomSubsetsPickModeTokens, GEOMSUBSETS_PICK_MODE_TOKENS); + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaHydra/mayaPlugin/tokens.h b/lib/mayaHydra/mayaPlugin/tokens.h index 6cf8e20f7f..cf007ceb39 100644 --- a/lib/mayaHydra/mayaPlugin/tokens.h +++ b/lib/mayaHydra/mayaPlugin/tokens.h @@ -31,6 +31,21 @@ PXR_NAMESPACE_OPEN_SCOPE // This is not an exported API. TF_DECLARE_PUBLIC_TOKENS(MtohTokens, , MTOH_TOKENS); +// clang-format off +#define MAYAHYDRA_PICK_OPTIONVAR_TOKENS \ + ((GeomSubsetsPickMode, "mayaHydra_GeomSubsetsPickMode")) +// clang-format on + +TF_DECLARE_PUBLIC_TOKENS(MayaHydraPickOptionVars, MAYAHYDRA_PICK_OPTIONVAR_TOKENS); + +// clang-format off +#define GEOMSUBSETS_PICK_MODE_TOKENS \ + (None) \ + (Faces) +// clang-format on + +TF_DECLARE_PUBLIC_TOKENS(GeomSubsetsPickModeTokens, GEOMSUBSETS_PICK_MODE_TOKENS); + PXR_NAMESPACE_CLOSE_SCOPE #endif // MTOH_TOKENS_H diff --git a/lib/mayaHydra/mayaPlugin/viewCommand.cpp b/lib/mayaHydra/mayaPlugin/viewCommand.cpp index 75dad64369..960c517b9f 100644 --- a/lib/mayaHydra/mayaPlugin/viewCommand.cpp +++ b/lib/mayaHydra/mayaPlugin/viewCommand.cpp @@ -28,6 +28,8 @@ #include #include +#include + PXR_NAMESPACE_USING_DIRECTIVE namespace MAYAHYDRA_NS_DEF { @@ -92,6 +94,9 @@ constexpr auto _gitCommitLong = "-gitCommit"; constexpr auto _gitBranchLong = "-gitBranch"; constexpr auto _buildDateLong = "-buildDate"; +constexpr auto _usdVersion = "-uv"; +constexpr auto _usdVersionLong = "-usdVersion"; + constexpr auto _rendererId = "-r"; constexpr auto _rendererIdLong = "-renderer"; @@ -181,6 +186,8 @@ MSyntax MtohViewCmd::createSyntax() syntax.addFlag(_gitBranch, _gitBranchLong); syntax.addFlag(_buildDate, _buildDateLong); + syntax.addFlag(_usdVersion, _usdVersionLong); + return syntax; } @@ -303,6 +310,8 @@ MStatus MtohViewCmd::doIt(const MArgList& args) setResult(MhBuildInfo::gitBranch()); } else if (db.isFlagSet(_buildDate)) { setResult(MhBuildInfo::buildDate()); + } else if (db.isFlagSet(_usdVersion)) { + setResult(PXR_VERSION); } return MS::kSuccess; } diff --git a/modules/mayaHydra.mod.template b/modules/mayaHydra.mod.template index 8deb2f43e7..96f5882164 100644 --- a/modules/mayaHydra.mod.template +++ b/modules/mayaHydra.mod.template @@ -13,6 +13,6 @@ PXR_MTLX_STDLIB_SEARCH_PATHS+:=libraries icons: plug-ins: lib/maya presets: -scripts: +scripts: scripts resources: ${PXR_OVERRIDE_PLUGINPATH_NAME}+:=lib/usd diff --git a/modules/mayaHydra_Win.mod.template b/modules/mayaHydra_Win.mod.template index 760f44306d..1902895cfa 100644 --- a/modules/mayaHydra_Win.mod.template +++ b/modules/mayaHydra_Win.mod.template @@ -16,7 +16,7 @@ PXR_MTLX_STDLIB_SEARCH_PATHS+:=libraries icons: plug-ins: lib/maya presets: -scripts: +scripts: scripts resources: PATH+:=lib ${PXR_OVERRIDE_PLUGINPATH_NAME}+:=lib/usd diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt new file mode 100644 index 0000000000..64935cbf36 --- /dev/null +++ b/scripts/CMakeLists.txt @@ -0,0 +1,13 @@ +set(MEL_SCRIPT_FILES + mayaHydra_registerUIStrings.mel + mayaHydra_registerUI_load.mel + mayaHydra_registerUI_unload.mel + mayaHydra_registerUI_batch_load.mel + mayaHydra_registerUI_batch_unload.mel + mayaHydra_GeomSubsetsPickMode.mel +) + +install( + FILES ${MEL_SCRIPT_FILES} + DESTINATION ${CMAKE_INSTALL_PREFIX}/scripts +) diff --git a/scripts/mayaHydra_GeomSubsetsPickMode.mel b/scripts/mayaHydra_GeomSubsetsPickMode.mel new file mode 100644 index 0000000000..561e27da78 --- /dev/null +++ b/scripts/mayaHydra_GeomSubsetsPickMode.mel @@ -0,0 +1,208 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Contents of this file are largely adaptations of MayaUSD code for Kind and Point Instance picking modes UI setup. +// See mayaUsdMenu.mel in MayaUSD : https://github.com/Autodesk/maya-usd/blob/d7e4ee276f752a745e563f1dfb54e932b11c013f/plugin/adsk/scripts/mayaUsdMenu.mel + +// addMenuCallback and removeMenuCallback were copied over from MayaUSD +// See here : https://github.com/Autodesk/maya-usd/blob/d7e4ee276f752a745e563f1dfb54e932b11c013f/plugin/adsk/scripts/mayaUsdMenu.mel#L53-L72 + +// Safely add a post menu callback to a menu +proc addMenuCallback(string $menuName, string $cmd) { + string $existingCallbacks = `menu -q -pmc $menuName`; + // append the callback + menu -e -pmc ($existingCallbacks + ";" + $cmd + ";") $menuName; +} + +// Safely remove a post menu callback to a menu +proc removeMenuCallback(string $menuName, string $cmd) { + string $existingCallbacks = `menu -q -pmc $menuName`; + // remove our callback from the string of callbacks + string $newCallbacks = + `substitute (";"+$cmd+".*;") $existingCallbacks ""`; + menu -e -pmc $newCallbacks $menuName; +} + +// Check if a post menu callback is present on a menu +proc int hasMenuCallback(string $menuName, string $cmd) { + string $existingCallbacks = `menu -q -pmc $menuName`; + return `gmatch $existingCallbacks ("*" + $cmd + "*")`; +} + +// Global variables to keep track of our UI elements +global string $gMayaHydra_GeomSubsetsPickMode_Divider = ""; +global string $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup = ""; +global string $gMayaHydra_GeomSubsetsPickMode_RadioButtons[] = {}; + +// Helper function to get the GeomSubsets pick mode. +global proc string mayaHydra_GeomSubsetsPickMode_GetMode() { + string $mode = ""; + if (`optionVar -exists "mayaHydra_GeomSubsetsPickMode"`) { + $mode = `optionVar -q "mayaHydra_GeomSubsetsPickMode"`; + } + return $mode; +} + +// Helper function to set the GeomSubsets pick mode. +global proc mayaHydra_GeomSubsetsPickMode_SetMode(string $mode) { + optionVar -stringValue "mayaHydra_GeomSubsetsPickMode" $mode; +} + +// Main entry point to create the GeomSubsets UI +global proc mayaHydra_GeomSubsetsPickMode_SetupUI() { + if (`mayaHydra -usdVersion` < 2403) { + return; + } + + mayaHydra_GeomSubsetsPickMode_SetupRuntimeCommands; + global string $gMainSelectMenu; // Maya's "Select" menu + $callbackExists = hasMenuCallback($gMainSelectMenu, "mayaHydra_GeomSubsetsPickModeMenu_SelectMenuOpenedCallback"); + if (!$callbackExists) { + addMenuCallback($gMainSelectMenu, "mayaHydra_GeomSubsetsPickModeMenu_SelectMenuOpenedCallback"); + } +} + +// Main entry point to delete the GeomSubsets UI +global proc mayaHydra_GeomSubsetsPickMode_TeardownUI() { + if (`mayaHydra -usdVersion` < 2403) { + return; + } + + global string $gMainSelectMenu; // Maya's "Select" menu + removeMenuCallback($gMainSelectMenu, "mayaHydra_GeomSubsetsPickModeMenu_SelectMenuOpenedCallback"); + + global string $gMayaHydra_GeomSubsetsPickMode_Divider; + if (`menuItem -q -exists $gMayaHydra_GeomSubsetsPickMode_Divider`) { + deleteUI -menuItem $gMayaHydra_GeomSubsetsPickMode_Divider; + } + $gMayaHydra_GeomSubsetsPickMode_Divider = ""; + + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtons[]; + for ($radioButton in $gMayaHydra_GeomSubsetsPickMode_RadioButtons) { + if (`menuItem -q -exists $radioButton`) { + deleteUI -menuItem $radioButton; + } + } + clear($gMayaHydra_GeomSubsetsPickMode_RadioButtons); + + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup; + if (`radioMenuItemCollection -q -exists $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup`) { + deleteUI -radioMenuItemCollection $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup; + } + $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup = ""; +} + +global proc mayaHydra_GeomSubsetsPickMode_SetupRuntimeCommands() { + if (!`runTimeCommand -exists mayaHydra_GeomSubsetsPickMode_SetNone`) { + runTimeCommand -default true -plugin "mayaHydra" + -label `getMayaHydraString("kUSDGeomSubsetsPickMode_None")` + -annotation `getMayaHydraString("kUSDGeomSubsetsPickMode_NoneAnn")` + -category "Menu items.Maya USD" + -command ("mayaHydra_GeomSubsetsPickMode_SetMode(\"None\")") + mayaHydra_GeomSubsetsPickMode_SetNone; + } + if (!`runTimeCommand -exists mayaHydra_GeomSubsetsPickMode_SetFaces`) { + runTimeCommand -default true -plugin "mayaHydra" + -label `getMayaHydraString("kUSDGeomSubsetsPickMode_Faces")` + -annotation `getMayaHydraString("kUSDGeomSubsetsPickMode_FacesAnn")` + -category "Menu items.Maya USD" + -command ("mayaHydra_GeomSubsetsPickMode_SetMode(\"Faces\")") + mayaHydra_GeomSubsetsPickMode_SetFaces; + } +} + +global proc mayaHydra_GeomSubsetsPickModeMenu_SelectMenuOpenedCallback() { + // Explanation of how we augment MayaUSD's selection modes menu with our custom options + // for GeomSubsets picking : + // To create its selection modes menu, MayaUSD, on plugin UI load, will setup a callback + // on when the "Select" menu in Maya is opened. The callback will then create the selection + // modes submenu and its menu items. So what we do in order to add our own menu items is that + // we also add our own callback on the "Select" menu. However, we can't count on the order + // in which callbacks will be registered and processed, and just blindly add the menu items here. + // To work around this, we thus create the UI elements in a method that will be called by an idle + // event/scriptJob, which will be executed after the "Select" menu open callbacks have been + // processed. The USD selection modes menu should then exist, and we can add our menu items then. + + // If MayaUSD is not loaded, the USD selection modes menu won't exist, so no need to try and add + // our own menu items. + if (!`pluginInfo -q -loaded mayaUsdPlugin`) { + return; + } + + // If our custom UI elements name is empty, then they do not exist or have been torn down previously, + // so create them. Note that we check that all UI elements have empty names : normally they should + // always either all have a name and exist, or all have no name and not exist. + global string $gMayaHydra_GeomSubsetsPickMode_Divider; + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup; + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtons[]; + if ($gMayaHydra_GeomSubsetsPickMode_Divider == "" + && $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup == "" + && `size($gMayaHydra_GeomSubsetsPickMode_RadioButtons)` == 0) { + scriptJob -idleEvent "mayaHydra_GeomSubsetsPickModeMenu_CreateMenuItems" -runOnce true; + } +} + +global proc mayaHydra_GeomSubsetsPickModeMenu_CreateMenuItems() { + global string $gMayaUsdSelectModeSubMenu; + if ($gMayaUsdSelectModeSubMenu == "" || !`menuItem -q -exists $gMayaUsdSelectModeSubMenu`) { + print "Error : USD selection submenu was not found, could not create GeomSubsets pick mode UI.\n"; + return; + } + + // Store the current parent menu and change it to the USD selection submenu + $prevParent = `setParent -q -menu`; + setParent -menu $gMayaUsdSelectModeSubMenu; + + global string $gMayaHydra_GeomSubsetsPickMode_Divider; + $dividerLabel = getMayaHydraString("kGeomSubsets"); + $gMayaHydra_GeomSubsetsPickMode_Divider = `menuItem -divider true -dividerLabel $dividerLabel`; + + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup; + $gMayaHydra_GeomSubsetsPickMode_RadioButtonsGroup = `radioMenuItemCollection`; + global string $gMayaHydra_GeomSubsetsPickMode_RadioButtons[]; + $gMayaHydra_GeomSubsetsPickMode_RadioButtons[0] = `menuItem -radioButton on -runTimeCommand ("mayaHydra_GeomSubsetsPickMode_SetNone") mayaHydra_GeomSubsetsPickMode_None`; + $gMayaHydra_GeomSubsetsPickMode_RadioButtons[1] = `menuItem -radioButton off -runTimeCommand ("mayaHydra_GeomSubsetsPickMode_SetFaces") mayaHydra_GeomSubsetsPickMode_Faces`; + + mayaHydra_GeomSubsetsPickModeMenu_UpdateRadioButtons(); + + scriptJob -parent $gMayaUsdSelectModeSubMenu + -optionVarChanged "mayaHydra_GeomSubsetsPickMode" "mayaHydra_GeomSubsetsPickModeMenu_UpdateRadioButtons"; + + // Restore the previous parent menu + setParent -menu $prevParent; +} + +// Update the menu item radio buttons in the GeomSubsets pick mode UI +global proc mayaHydra_GeomSubsetsPickModeMenu_UpdateRadioButtons() { + // Note: we do all string compares as case-insensitive (lowercase) + // as the menu labels are capitalized. + string $pickMode = `tolower(mayaHydra_GeomSubsetsPickMode_GetMode())`; + switch($pickMode) { + case "": + menuItem -e -radioButton on mayaHydra_GeomSubsetsPickMode_None; + break; + default: + // Enable the menu item based on the label. + global string $gMayaUsdSelectModeSubMenu; + $menuItems = `menu -q -itemArray $gMayaUsdSelectModeSubMenu`; + for($i = 0; $i < size($menuItems); $i++) { + string $label = `menuItem -q -label $menuItems[$i]`; + if(`tolower($label)` == $pickMode) { + menuItem -e -radioButton on $menuItems[$i]; + break; + } + } + } +} diff --git a/scripts/mayaHydra_registerUIStrings.mel b/scripts/mayaHydra_registerUIStrings.mel new file mode 100644 index 0000000000..baaba6f144 --- /dev/null +++ b/scripts/mayaHydra_registerUIStrings.mel @@ -0,0 +1,40 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Largely copied from MayaUSD's mayaUSDRegisterStrings.mel +// See here : https://github.com/Autodesk/maya-usd/blob/d7e4ee276f752a745e563f1dfb54e932b11c013f/plugin/adsk/scripts/mayaUSDRegisterStrings.mel + +proc registerMayaHydraString(string $key, string $value) +{ + registerPluginResource("mayaHydra", $key, $value); +} + +global proc string getMayaHydraString(string $key) +{ + return getPluginResource("mayaHydra", $key); +} + +global proc mayaHydra_registerUIStrings() +{ + // Register the UI strings + registerMayaHydraString("kGeomSubsets", "GeomSubsets (Hydra only)"); + registerMayaHydraString("kUSDGeomSubsetsPickMode_None", "None"); + registerMayaHydraString("kUSDGeomSubsetsPickMode_NoneAnn", "Don't select GeomSubsets."); + registerMayaHydraString("kUSDGeomSubsetsPickMode_Faces", "Faces"); + registerMayaHydraString("kUSDGeomSubsetsPickMode_FacesAnn", "Select GeomSubsets containing faces."); + + // Load any localized resources + loadPluginLanguageResources("mayaHydra", "mayaHydra.pres.mel"); +} diff --git a/scripts/mayaHydra_registerUI_batch_load.mel b/scripts/mayaHydra_registerUI_batch_load.mel new file mode 100644 index 0000000000..1b6a7fe2a0 --- /dev/null +++ b/scripts/mayaHydra_registerUI_batch_load.mel @@ -0,0 +1,21 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +global proc mayaHydra_registerUI_batch_load() +// Callback registered with the MFnPlugin for when the plugin is loaded +// in batch mode. +// Do not currently have anything we need to handle. +{ +} diff --git a/scripts/mayaHydra_registerUI_batch_unload.mel b/scripts/mayaHydra_registerUI_batch_unload.mel new file mode 100644 index 0000000000..e11e94084d --- /dev/null +++ b/scripts/mayaHydra_registerUI_batch_unload.mel @@ -0,0 +1,21 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +global proc mayaHydra_registerUI_batch_unload() +// Callback registered with the MFnPlugin for when the plugin is unloaded +// in batch mode. +// Do not currently have anything we need to handle. +{ +} diff --git a/scripts/mayaHydra_registerUI_load.mel b/scripts/mayaHydra_registerUI_load.mel new file mode 100644 index 0000000000..c40c9c6a13 --- /dev/null +++ b/scripts/mayaHydra_registerUI_load.mel @@ -0,0 +1,22 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +global proc mayaHydra_registerUI_load() +// Callback registered with the MFnPlugin for when the plugin is loaded. +// Used to initialize any UI we create. +{ + source "mayaHydra_GeomSubsetsPickMode.mel"; + mayaHydra_GeomSubsetsPickMode_SetupUI(); +} diff --git a/scripts/mayaHydra_registerUI_unload.mel b/scripts/mayaHydra_registerUI_unload.mel new file mode 100644 index 0000000000..60e429af00 --- /dev/null +++ b/scripts/mayaHydra_registerUI_unload.mel @@ -0,0 +1,22 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +global proc mayaHydra_registerUI_unload() +// Callback registered with the MFnPlugin for when the plugin is unloaded. +// Used to remove any UI we create. +{ + source "mayaHydra_GeomSubsetsPickMode.mel"; + mayaHydra_GeomSubsetsPickMode_TeardownUI(); +} diff --git a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt index 1b88840cea..fa500bb14b 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt @@ -67,6 +67,7 @@ set(INTERACTIVE_TEST_SCRIPT_FILES cpp/testUsdPickKind.py cpp/testNurbsSurfaces.py cpp/testPointInstancingWireframeHighlight.py + cpp/testGeomSubsetsPicking.py ) #Add this test only if the MayaUsd_FOUND (so also MAYAUSDAPI_LIBRARY) has been found during compile time. diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt index 2d96417632..47dc315669 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt @@ -41,6 +41,7 @@ target_sources(${TARGET_NAME} testUsdPicking.cpp testNurbsSurfaces.cpp testPointInstancingWireframeHighlight.cpp + testGeomSubsetsPicking.cpp ) # ----------------------------------------------------------------------------- diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.cpp new file mode 100644 index 0000000000..2c8a778ac8 --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.cpp @@ -0,0 +1,210 @@ +// Copyright 2024 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "testUtils.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +using namespace MayaHydra; + +namespace { + +#if PXR_VERSION >= 2403 +const std::string kStageUfePathSegment = "|GeomSubsetsPickingTestScene|GeomSubsetsPickingTestSceneShape"; + +const std::string kCubeMeshUfePathSegment = "/Root/CubeMeshXform/CubeMesh"; +const std::string kSphereMeshUfePathSegment = "/Root/SphereMeshXform/SphereMesh"; + +const std::string kCubeUpperHalfName = "CubeUpperHalf"; +const std::string kSphereUpperHalfName = "SphereUpperHalf"; + +const std::string kCubeUpperHalfMarkerUfePathSegment = "/Root/CubeUpperHalfMarker"; +const std::string kCubeLowerHalfMarkerUfePathSegment = "/Root/CubeLowerHalfMarker"; +const std::string kSphereInstanceUpperHalfMarkerUfePathSegment = "/Root/SphereInstanceUpperHalfMarker"; +const std::string kSphereInstanceLowerHalfMarkerUfePathSegment = "/Root/SphereInstanceLowerHalfMarker"; + +void assertUnselected(const SceneIndexInspector& inspector, const FindPrimPredicate& primPredicate) +{ + PrimEntriesVector primEntries = inspector.FindPrims(primPredicate); + for (const auto& primEntry : primEntries) { + HdSelectionsSchema selectionsSchema = HdSelectionsSchema::GetFromParent(primEntry.prim.dataSource); + ASSERT_FALSE(selectionsSchema.IsDefined()); + } +} + +void assertSelected(const SceneIndexInspector& inspector, const FindPrimPredicate& primPredicate) +{ + PrimEntriesVector primEntries = inspector.FindPrims(primPredicate); + ASSERT_FALSE(primEntries.empty()); + + for (const auto& primEntry : primEntries) { + HdSelectionsSchema selectionsSchema = HdSelectionsSchema::GetFromParent(primEntry.prim.dataSource); + ASSERT_TRUE(selectionsSchema.IsDefined()); + ASSERT_EQ(selectionsSchema.GetNumElements(), 1u); + HdSelectionSchema selectionSchema = selectionsSchema.GetElement(0); + ASSERT_TRUE(selectionSchema.GetFullySelected()); + } +} + +void testPicking(const Ufe::Path& clickMarkerUfePath, const Ufe::Path& selectedObjectUfePath) +{ + const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); + ASSERT_GT(sceneIndices.size(), 0u); + SceneIndexInspector inspector(sceneIndices.front()); + + // Preconditions + auto ufeSelection = Ufe::GlobalSelection::get(); + ASSERT_TRUE(ufeSelection->empty()); + + const auto selectionSceneIndex = findSelectionSceneIndexInTree(inspector.GetSceneIndex()); + ASSERT_TRUE(selectionSceneIndex); + + const auto selectedObjectSceneIndexPaths = selectionSceneIndex->SceneIndexPaths(selectedObjectUfePath); + + for (const auto& selectedObjectSceneIndexPath : selectedObjectSceneIndexPaths) { + HdSceneIndexPrim selectedObjectSceneIndexPrim = inspector.GetSceneIndex()->GetPrim(selectedObjectSceneIndexPath); + HdSelectionsSchema selectionsSchema = HdSelectionsSchema::GetFromParent(selectedObjectSceneIndexPrim.dataSource); + ASSERT_EQ(selectionsSchema.IsDefined(), false); + } + + // Picking + M3dView active3dView = M3dView::active3dView(); + const auto clickMarkerSceneIndexPath = selectionSceneIndex->SceneIndexPath(clickMarkerUfePath); + auto primMouseCoords = getPrimMouseCoords(inspector.GetSceneIndex()->GetPrim(clickMarkerSceneIndexPath), active3dView); + + mouseClick(Qt::MouseButton::LeftButton, active3dView.widget(), primMouseCoords); + active3dView.refresh(); + + // Postconditions + ASSERT_EQ(ufeSelection->size(), 1u); + ASSERT_TRUE(ufeSelection->contains(selectedObjectUfePath)); + + for (const auto& selectedObjectSceneIndexPath : selectedObjectSceneIndexPaths) { + HdSceneIndexPrim selectedObjectSceneIndexPrim = inspector.GetSceneIndex()->GetPrim(selectedObjectSceneIndexPath); + HdSelectionsSchema selectionsSchema = HdSelectionsSchema::GetFromParent(selectedObjectSceneIndexPrim.dataSource); + ASSERT_EQ(selectionsSchema.IsDefined(), true); + ASSERT_EQ(selectionsSchema.GetNumElements(), 1u); + ASSERT_TRUE(selectionsSchema.GetElement(0).GetFullySelected()); + } +} +#endif + +} // namespace + +TEST(TestGeomSubsetsPicking, geomSubsetPicking) +{ +#if PXR_VERSION < 2403 + GTEST_SKIP() << "Skipping test, USD version used does not support GeomSubset prims."; +#else + const auto cubeUpperHalfMarkerUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kCubeUpperHalfMarkerUfePathSegment); + const auto cubeUpperHalfUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kCubeMeshUfePathSegment + "/" + kCubeUpperHalfName); + testPicking(cubeUpperHalfMarkerUfePath, cubeUpperHalfUfePath); +#endif +} + +TEST(TestGeomSubsetsPicking, fallbackPicking) +{ +#if PXR_VERSION < 2403 + GTEST_SKIP() << "Skipping test, USD version used does not support GeomSubset prims."; +#else + const auto cubeLowerHalfMarkerUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kCubeLowerHalfMarkerUfePathSegment); + const auto cubeMeshUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kCubeMeshUfePathSegment); + testPicking(cubeLowerHalfMarkerUfePath, cubeMeshUfePath); +#endif +} + +TEST(TestGeomSubsetsPicking, instanceGeomSubsetPicking) +{ +#if PXR_VERSION < 2403 + GTEST_SKIP() << "Skipping test, USD version used does not support GeomSubset prims."; +#else + const auto sphereInstanceUpperHalfMarkerUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kSphereInstanceUpperHalfMarkerUfePathSegment); + const auto sphereUpperHalfUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kSphereMeshUfePathSegment + "/" + kSphereUpperHalfName); + testPicking(sphereInstanceUpperHalfMarkerUfePath, sphereUpperHalfUfePath); +#endif +} + +TEST(TestGeomSubsetsPicking, instanceFallbackPicking) +{ +#if PXR_VERSION < 2403 + GTEST_SKIP() << "Skipping test, USD version used does not support GeomSubset prims."; +#else + const auto sphereInstanceLowerHalfMarkerUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kSphereInstanceLowerHalfMarkerUfePathSegment); + const auto sphereMeshUfePath = Ufe::PathString::path(kStageUfePathSegment + "," + kSphereMeshUfePathSegment); + testPicking(sphereInstanceLowerHalfMarkerUfePath, sphereMeshUfePath); +#endif +} + +TEST(TestGeomSubsetsPicking, marqueeSelect) +{ +#if PXR_VERSION < 2403 + GTEST_SKIP() << "Skipping test, USD version used does not support GeomSubset prims."; +#else + const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); + ASSERT_GT(sceneIndices.size(), 0u); + SceneIndexInspector inspector(sceneIndices.front()); + + const auto cubeMeshUfePathString = kStageUfePathSegment + "," + kCubeMeshUfePathSegment; + const auto cubeUpperHalfUfePath = Ufe::PathString::path(cubeMeshUfePathString + "/" + kCubeUpperHalfName); + + const auto sphereMeshUfePathString = kStageUfePathSegment + "," + kSphereMeshUfePathSegment; + const auto sphereUpperHalfUfePath = Ufe::PathString::path(sphereMeshUfePathString + "/" + kSphereUpperHalfName); + + std::vector geomSubsetNamesToSelect = {"CubeUpperHalf", "SphereUpperHalf"}; + + // Preconditions + auto ufeSelection = Ufe::GlobalSelection::get(); + ASSERT_TRUE(ufeSelection->empty()); + + for (const auto& geomSubsetName : geomSubsetNamesToSelect) { + assertUnselected(inspector, PrimNamePredicate(geomSubsetName)); + } + + // Marquee selection + M3dView active3dView = M3dView::active3dView(); + + int offsetFromBorder = 10; + QPoint topLeftMouseCoords(0 + offsetFromBorder, 0 + offsetFromBorder); + QPoint bottomRightMouseCoords(active3dView.portWidth() - offsetFromBorder, active3dView.portHeight() - offsetFromBorder); + + mousePress(Qt::MouseButton::LeftButton, active3dView.widget(), topLeftMouseCoords); + mouseMoveTo(active3dView.widget(), bottomRightMouseCoords); + mouseRelease(Qt::MouseButton::LeftButton, active3dView.widget(), bottomRightMouseCoords); + active3dView.refresh(); + + // Postconditions + ASSERT_EQ(ufeSelection->size(), 2u); + ASSERT_TRUE(ufeSelection->contains(cubeUpperHalfUfePath)); + ASSERT_TRUE(ufeSelection->contains(sphereUpperHalfUfePath)); + + for (const auto& geomSubsetName : geomSubsetNamesToSelect) { + assertSelected(inspector, PrimNamePredicate(geomSubsetName)); + } +#endif +} diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.py b/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.py new file mode 100644 index 0000000000..ce488048fa --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testGeomSubsetsPicking.py @@ -0,0 +1,65 @@ +# Copyright 2024 Autodesk +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import maya.cmds as cmds +import fixturesUtils +import mtohUtils +import testUtils +import usdUtils + +from testUtils import PluginLoaded + +class TestGeomSubsetsPicking(mtohUtils.MayaHydraBaseTestCase): + # MayaHydraBaseTestCase.setUpClass requirement. + _file = __file__ + + def loadUsdScene(self): + usdScenePath = testUtils.getTestScene('testGeomSubsetsPicking', 'GeomSubsetsPickingTestScene.usda') + usdUtils.createStageFromFile(usdScenePath) + + def setUp(self): + super(TestGeomSubsetsPicking, self).setUp() + self.loadUsdScene() + cmds.select(clear=True) + cmds.optionVar( + sv=('mayaHydra_GeomSubsetsPickMode', 'Faces')) + # Used to ensure the fallback picking behavior works when clicking on a non-GeomSubset + cmds.optionVar( + sv=('mayaUsd_PointInstancesPickMode', 'Prototypes')) + cmds.setAttr('persp.translate', 0, 0, 15, type='float3') + cmds.setAttr('persp.rotate', 0, 0, 0, type='float3') + cmds.refresh() + + def test_GeomSubsetPicking(self): + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="TestGeomSubsetsPicking.geomSubsetPicking") + + def test_FallbackPicking(self): + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="TestGeomSubsetsPicking.fallbackPicking") + + def test_InstanceGeomSubsetPicking(self): + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="TestGeomSubsetsPicking.instanceGeomSubsetPicking") + + def test_InstanceFallbackPicking(self): + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="TestGeomSubsetsPicking.instanceFallbackPicking") + + def test_MarqueeSelect(self): + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="TestGeomSubsetsPicking.marqueeSelect") + +if __name__ == '__main__': + fixturesUtils.runTests(globals()) diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.cpp index a153d20476..4eaa058d6b 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.cpp @@ -65,9 +65,6 @@ TEST(TestUsdPointInstancePicking, pickPointInstance) mouseClick(Qt::MouseButton::LeftButton, active3dView.widget(), primMouseCoords); active3dView.refresh(); - // When picking on the boundary of multiple objects, one Hydra pick hit per - // object is returned. Therefore test that the expected selected path is - // in the selection. - ASSERT_GE(sn->size(), 1u); + ASSERT_EQ(sn->size(), 1u); ASSERT_TRUE(sn->contains(selected)); } diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.py b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.py index 6c71d965fd..f7586bd1cd 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.py +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancePicking.py @@ -40,8 +40,8 @@ def loadUsdScene(self): def setUp(self): super(TestUsdPointInstancePicking, self).setUp() self.loadUsdScene() - cmds.setAttr('persp.translate', 19.3, 13.7, 11.4, type='float3') - cmds.setAttr('persp.rotate', -33.4, 63.0, 0, type='float3') + cmds.setAttr('persp.translate', 15, 15, 10, type='float3') + cmds.setAttr('persp.rotate', -40, 60, 0, type='float3') cmds.refresh() def test_PickPointInstancer(self): diff --git a/test/testSamples/testGeomSubsetsPicking/GeomSubsetsPickingTestScene.usda b/test/testSamples/testGeomSubsetsPicking/GeomSubsetsPickingTestScene.usda new file mode 100644 index 0000000000..85ef2ddba6 --- /dev/null +++ b/test/testSamples/testGeomSubsetsPicking/GeomSubsetsPickingTestScene.usda @@ -0,0 +1,96 @@ +#usda 1.0 +( + defaultPrim = "Root" + metersPerUnit = 0.01 + upAxis = "Z" +) + +def Xform "Root" +{ + def Xform "CubeMeshXform" + { + double3 xformOp:translate = (-2, 0, 0) + float3 xformOp:scale = (2, 2, 2) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:scale"] + + def Mesh "CubeMesh" ( + references = @./UpperHalfGeomSubsetCube.usda@ + ) + { + over "CubeUpperHalf" ( + prepend apiSchemas = ["MaterialBindingAPI"] + ) + { + uniform token familyName = "materialBind" + rel material:binding = + } + } + } + + def Xform "SphereMeshXform" + { + double3 xformOp:translate = (-2, 2, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + + def Mesh "SphereMesh" ( + references = @./UpperHalfGeomSubsetSphere.usda@ + ) + { + over "SphereUpperHalf" ( + prepend apiSchemas = ["MaterialBindingAPI"] + ) + { + uniform token familyName = "materialBind" + rel material:binding = + } + } + } + + def PointInstancer "SphereInstancer" + { + point3f[] positions = [(2, 0, 0), (2, 2, 0)] + int[] protoIndices = [0, 0] + rel prototypes = [ + , + ] + } + + def Xform "CubeUpperHalfMarker" + { + double3 xformOp:translate = (-2, 0.5, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + } + + def Xform "CubeLowerHalfMarker" + { + double3 xformOp:translate = (-2, -0.5, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + } + + def Xform "SphereInstanceUpperHalfMarker" + { + double3 xformOp:translate = (2, 0.5, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + } + + def Xform "SphereInstanceLowerHalfMarker" + { + double3 xformOp:translate = (2, -0.5, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + } +} + +def Scope "mtl" +{ + def Material "GeomSubsetMaterial" + { + token outputs:surface.connect = + + def Shader "GeomSubsetMaterial" + { + uniform token info:id = "UsdPreviewSurface" + token outputs:surface + } + } +} + diff --git a/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetCube.usda b/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetCube.usda new file mode 100644 index 0000000000..aaadc8c867 --- /dev/null +++ b/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetCube.usda @@ -0,0 +1,24 @@ +#usda 1.0 +( + defaultPrim = "UpperHalfGeomSubsetCube" + metersPerUnit = 0.01 + upAxis = "Z" +) + +def Mesh "UpperHalfGeomSubsetCube" ( + kind = "component" +) +{ + uniform bool doubleSided = 1 + float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)] + int[] faceVertexCounts = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4] + int[] faceVertexIndices = [0, 1, 12, 11, 1, 2, 13, 12, 2, 3, 14, 13, 3, 4, 15, 14, 4, 5, 16, 15, 5, 6, 17, 16, 6, 7, 18, 17, 7, 8, 19, 18, 8, 9, 20, 19, 9, 10, 21, 20, 11, 12, 23, 22, 12, 13, 24, 23, 13, 14, 25, 24, 14, 15, 26, 25, 15, 16, 27, 26, 16, 17, 28, 27, 17, 18, 29, 28, 18, 19, 30, 29, 19, 20, 31, 30, 20, 21, 32, 31, 22, 23, 34, 33, 23, 24, 35, 34, 24, 25, 36, 35, 25, 26, 37, 36, 26, 27, 38, 37, 27, 28, 39, 38, 28, 29, 40, 39, 29, 30, 41, 40, 30, 31, 42, 41, 31, 32, 43, 42, 33, 34, 45, 44, 34, 35, 46, 45, 35, 36, 47, 46, 36, 37, 48, 47, 37, 38, 49, 48, 38, 39, 50, 49, 39, 40, 51, 50, 40, 41, 52, 51, 41, 42, 53, 52, 42, 43, 54, 53, 44, 45, 56, 55, 45, 46, 57, 56, 46, 47, 58, 57, 47, 48, 59, 58, 48, 49, 60, 59, 49, 50, 61, 60, 50, 51, 62, 61, 51, 52, 63, 62, 52, 53, 64, 63, 53, 54, 65, 64, 55, 56, 67, 66, 56, 57, 68, 67, 57, 58, 69, 68, 58, 59, 70, 69, 59, 60, 71, 70, 60, 61, 72, 71, 61, 62, 73, 72, 62, 63, 74, 73, 63, 64, 75, 74, 64, 65, 76, 75, 66, 67, 78, 77, 67, 68, 79, 78, 68, 69, 80, 79, 69, 70, 81, 80, 70, 71, 82, 81, 71, 72, 83, 82, 72, 73, 84, 83, 73, 74, 85, 84, 74, 75, 86, 85, 75, 76, 87, 86, 77, 78, 89, 88, 78, 79, 90, 89, 79, 80, 91, 90, 80, 81, 92, 91, 81, 82, 93, 92, 82, 83, 94, 93, 83, 84, 95, 94, 84, 85, 96, 95, 85, 86, 97, 96, 86, 87, 98, 97, 88, 89, 100, 99, 89, 90, 101, 100, 90, 91, 102, 101, 91, 92, 103, 102, 92, 93, 104, 103, 93, 94, 105, 104, 94, 95, 106, 105, 95, 96, 107, 106, 96, 97, 108, 107, 97, 98, 109, 108, 99, 100, 111, 110, 100, 101, 112, 111, 101, 102, 113, 112, 102, 103, 114, 113, 103, 104, 115, 114, 104, 105, 116, 115, 105, 106, 117, 116, 106, 107, 118, 117, 107, 108, 119, 118, 108, 109, 120, 119, 110, 111, 122, 121, 111, 112, 123, 122, 112, 113, 124, 123, 113, 114, 125, 124, 114, 115, 126, 125, 115, 116, 127, 126, 116, 117, 128, 127, 117, 118, 129, 128, 118, 119, 130, 129, 119, 120, 131, 130, 121, 122, 133, 132, 122, 123, 134, 133, 123, 124, 135, 134, 124, 125, 136, 135, 125, 126, 137, 136, 126, 127, 138, 137, 127, 128, 139, 138, 128, 129, 140, 139, 129, 130, 141, 140, 130, 131, 142, 141, 132, 133, 144, 143, 133, 134, 145, 144, 134, 135, 146, 145, 135, 136, 147, 146, 136, 137, 148, 147, 137, 138, 149, 148, 138, 139, 150, 149, 139, 140, 151, 150, 140, 141, 152, 151, 141, 142, 153, 152, 143, 144, 155, 154, 144, 145, 156, 155, 145, 146, 157, 156, 146, 147, 158, 157, 147, 148, 159, 158, 148, 149, 160, 159, 149, 150, 161, 160, 150, 151, 162, 161, 151, 152, 163, 162, 152, 153, 164, 163, 154, 155, 166, 165, 155, 156, 167, 166, 156, 157, 168, 167, 157, 158, 169, 168, 158, 159, 170, 169, 159, 160, 171, 170, 160, 161, 172, 171, 161, 162, 173, 172, 162, 163, 174, 173, 163, 164, 175, 174, 165, 166, 177, 176, 166, 167, 178, 177, 167, 168, 179, 178, 168, 169, 180, 179, 169, 170, 181, 180, 170, 171, 182, 181, 171, 172, 183, 182, 172, 173, 184, 183, 173, 174, 185, 184, 174, 175, 186, 185, 176, 177, 188, 187, 177, 178, 189, 188, 178, 179, 190, 189, 179, 180, 191, 190, 180, 181, 192, 191, 181, 182, 193, 192, 182, 183, 194, 193, 183, 184, 195, 194, 184, 185, 196, 195, 185, 186, 197, 196, 187, 188, 199, 198, 188, 189, 200, 199, 189, 190, 201, 200, 190, 191, 202, 201, 191, 192, 203, 202, 192, 193, 204, 203, 193, 194, 205, 204, 194, 195, 206, 205, 195, 196, 207, 206, 196, 197, 208, 207, 198, 199, 210, 209, 199, 200, 211, 210, 200, 201, 212, 211, 201, 202, 213, 212, 202, 203, 214, 213, 203, 204, 215, 214, 204, 205, 216, 215, 205, 206, 217, 216, 206, 207, 218, 217, 207, 208, 219, 218, 209, 210, 221, 220, 210, 211, 222, 221, 211, 212, 223, 222, 212, 213, 224, 223, 213, 214, 225, 224, 214, 215, 226, 225, 215, 216, 227, 226, 216, 217, 228, 227, 217, 218, 229, 228, 218, 219, 230, 229, 220, 221, 232, 231, 221, 222, 233, 232, 222, 223, 234, 233, 223, 224, 235, 234, 224, 225, 236, 235, 225, 226, 237, 236, 226, 227, 238, 237, 227, 228, 239, 238, 228, 229, 240, 239, 229, 230, 241, 240, 231, 232, 243, 242, 232, 233, 244, 243, 233, 234, 245, 244, 234, 235, 246, 245, 235, 236, 247, 246, 236, 237, 248, 247, 237, 238, 249, 248, 238, 239, 250, 249, 239, 240, 251, 250, 240, 241, 252, 251, 242, 243, 254, 253, 243, 244, 255, 254, 244, 245, 256, 255, 245, 246, 257, 256, 246, 247, 258, 257, 247, 248, 259, 258, 248, 249, 260, 259, 249, 250, 261, 260, 250, 251, 262, 261, 251, 252, 263, 262, 253, 254, 265, 264, 254, 255, 266, 265, 255, 256, 267, 266, 256, 257, 268, 267, 257, 258, 269, 268, 258, 259, 270, 269, 259, 260, 271, 270, 260, 261, 272, 271, 261, 262, 273, 272, 262, 263, 274, 273, 264, 265, 276, 275, 265, 266, 277, 276, 266, 267, 278, 277, 267, 268, 279, 278, 268, 269, 280, 279, 269, 270, 281, 280, 270, 271, 282, 281, 271, 272, 283, 282, 272, 273, 284, 283, 273, 274, 285, 284, 275, 276, 287, 286, 276, 277, 288, 287, 277, 278, 289, 288, 278, 279, 290, 289, 279, 280, 291, 290, 280, 281, 292, 291, 281, 282, 293, 292, 282, 283, 294, 293, 283, 284, 295, 294, 284, 285, 296, 295, 286, 287, 298, 297, 287, 288, 299, 298, 288, 289, 300, 299, 289, 290, 301, 300, 290, 291, 302, 301, 291, 292, 303, 302, 292, 293, 304, 303, 293, 294, 305, 304, 294, 295, 306, 305, 295, 296, 307, 306, 297, 298, 309, 308, 298, 299, 310, 309, 299, 300, 311, 310, 300, 301, 312, 311, 301, 302, 313, 312, 302, 303, 314, 313, 303, 304, 315, 314, 304, 305, 316, 315, 305, 306, 317, 316, 306, 307, 318, 317, 308, 309, 320, 319, 309, 310, 321, 320, 310, 311, 322, 321, 311, 312, 323, 322, 312, 313, 324, 323, 313, 314, 325, 324, 314, 315, 326, 325, 315, 316, 327, 326, 316, 317, 328, 327, 317, 318, 329, 328, 319, 320, 331, 330, 320, 321, 332, 331, 321, 322, 333, 332, 322, 323, 334, 333, 323, 324, 335, 334, 324, 325, 336, 335, 325, 326, 337, 336, 326, 327, 338, 337, 327, 328, 339, 338, 328, 329, 340, 339, 330, 331, 342, 341, 331, 332, 343, 342, 332, 333, 344, 343, 333, 334, 345, 344, 334, 335, 346, 345, 335, 336, 347, 346, 336, 337, 348, 347, 337, 338, 349, 348, 338, 339, 350, 349, 339, 340, 351, 350, 341, 342, 353, 352, 342, 343, 354, 353, 343, 344, 355, 354, 344, 345, 356, 355, 345, 346, 357, 356, 346, 347, 358, 357, 347, 348, 359, 358, 348, 349, 360, 359, 349, 350, 361, 360, 350, 351, 362, 361, 352, 353, 364, 363, 353, 354, 365, 364, 354, 355, 366, 365, 355, 356, 367, 366, 356, 357, 368, 367, 357, 358, 369, 368, 358, 359, 370, 369, 359, 360, 371, 370, 360, 361, 372, 371, 361, 362, 373, 372, 363, 364, 375, 374, 364, 365, 376, 375, 365, 366, 377, 376, 366, 367, 378, 377, 367, 368, 379, 378, 368, 369, 380, 379, 369, 370, 381, 380, 370, 371, 382, 381, 371, 372, 383, 382, 372, 373, 384, 383, 374, 375, 386, 385, 375, 376, 387, 386, 376, 377, 388, 387, 377, 378, 389, 388, 378, 379, 390, 389, 379, 380, 391, 390, 380, 381, 392, 391, 381, 382, 393, 392, 382, 383, 394, 393, 383, 384, 395, 394, 385, 386, 397, 396, 386, 387, 398, 397, 387, 388, 399, 398, 388, 389, 400, 399, 389, 390, 401, 400, 390, 391, 402, 401, 391, 392, 403, 402, 392, 393, 404, 403, 393, 394, 405, 404, 394, 395, 406, 405, 396, 397, 408, 407, 397, 398, 409, 408, 398, 399, 410, 409, 399, 400, 411, 410, 400, 401, 412, 411, 401, 402, 413, 412, 402, 403, 414, 413, 403, 404, 415, 414, 404, 405, 416, 415, 405, 406, 417, 416, 407, 408, 419, 418, 408, 409, 420, 419, 409, 410, 421, 420, 410, 411, 422, 421, 411, 412, 423, 422, 412, 413, 424, 423, 413, 414, 425, 424, 414, 415, 426, 425, 415, 416, 427, 426, 416, 417, 428, 427, 418, 419, 430, 429, 419, 420, 431, 430, 420, 421, 432, 431, 421, 422, 433, 432, 422, 423, 434, 433, 423, 424, 435, 434, 424, 425, 436, 435, 425, 426, 437, 436, 426, 427, 438, 437, 427, 428, 439, 438, 429, 430, 1, 0, 430, 431, 2, 1, 431, 432, 3, 2, 432, 433, 4, 3, 433, 434, 5, 4, 434, 435, 6, 5, 435, 436, 7, 6, 436, 437, 8, 7, 437, 438, 9, 8, 438, 439, 10, 9, 351, 340, 329, 440, 362, 351, 440, 441, 373, 362, 441, 442, 384, 373, 442, 443, 395, 384, 443, 444, 406, 395, 444, 445, 417, 406, 445, 446, 428, 417, 446, 447, 439, 428, 447, 448, 10, 439, 448, 21, 440, 329, 318, 449, 441, 440, 449, 450, 442, 441, 450, 451, 443, 442, 451, 452, 444, 443, 452, 453, 445, 444, 453, 454, 446, 445, 454, 455, 447, 446, 455, 456, 448, 447, 456, 457, 21, 448, 457, 32, 449, 318, 307, 458, 450, 449, 458, 459, 451, 450, 459, 460, 452, 451, 460, 461, 453, 452, 461, 462, 454, 453, 462, 463, 455, 454, 463, 464, 456, 455, 464, 465, 457, 456, 465, 466, 32, 457, 466, 43, 458, 307, 296, 467, 459, 458, 467, 468, 460, 459, 468, 469, 461, 460, 469, 470, 462, 461, 470, 471, 463, 462, 471, 472, 464, 463, 472, 473, 465, 464, 473, 474, 466, 465, 474, 475, 43, 466, 475, 54, 467, 296, 285, 476, 468, 467, 476, 477, 469, 468, 477, 478, 470, 469, 478, 479, 471, 470, 479, 480, 472, 471, 480, 481, 473, 472, 481, 482, 474, 473, 482, 483, 475, 474, 483, 484, 54, 475, 484, 65, 476, 285, 274, 485, 477, 476, 485, 486, 478, 477, 486, 487, 479, 478, 487, 488, 480, 479, 488, 489, 481, 480, 489, 490, 482, 481, 490, 491, 483, 482, 491, 492, 484, 483, 492, 493, 65, 484, 493, 76, 485, 274, 263, 494, 486, 485, 494, 495, 487, 486, 495, 496, 488, 487, 496, 497, 489, 488, 497, 498, 490, 489, 498, 499, 491, 490, 499, 500, 492, 491, 500, 501, 493, 492, 501, 502, 76, 493, 502, 87, 494, 263, 252, 503, 495, 494, 503, 504, 496, 495, 504, 505, 497, 496, 505, 506, 498, 497, 506, 507, 499, 498, 507, 508, 500, 499, 508, 509, 501, 500, 509, 510, 502, 501, 510, 511, 87, 502, 511, 98, 503, 252, 241, 512, 504, 503, 512, 513, 505, 504, 513, 514, 506, 505, 514, 515, 507, 506, 515, 516, 508, 507, 516, 517, 509, 508, 517, 518, 510, 509, 518, 519, 511, 510, 519, 520, 98, 511, 520, 109, 512, 241, 230, 219, 513, 512, 219, 208, 514, 513, 208, 197, 515, 514, 197, 186, 516, 515, 186, 175, 517, 516, 175, 164, 518, 517, 164, 153, 519, 518, 153, 142, 520, 519, 142, 131, 109, 520, 131, 120, 330, 341, 521, 319, 341, 352, 522, 521, 352, 363, 523, 522, 363, 374, 524, 523, 374, 385, 525, 524, 385, 396, 526, 525, 396, 407, 527, 526, 407, 418, 528, 527, 418, 429, 529, 528, 429, 0, 11, 529, 319, 521, 530, 308, 521, 522, 531, 530, 522, 523, 532, 531, 523, 524, 533, 532, 524, 525, 534, 533, 525, 526, 535, 534, 526, 527, 536, 535, 527, 528, 537, 536, 528, 529, 538, 537, 529, 11, 22, 538, 308, 530, 539, 297, 530, 531, 540, 539, 531, 532, 541, 540, 532, 533, 542, 541, 533, 534, 543, 542, 534, 535, 544, 543, 535, 536, 545, 544, 536, 537, 546, 545, 537, 538, 547, 546, 538, 22, 33, 547, 297, 539, 548, 286, 539, 540, 549, 548, 540, 541, 550, 549, 541, 542, 551, 550, 542, 543, 552, 551, 543, 544, 553, 552, 544, 545, 554, 553, 545, 546, 555, 554, 546, 547, 556, 555, 547, 33, 44, 556, 286, 548, 557, 275, 548, 549, 558, 557, 549, 550, 559, 558, 550, 551, 560, 559, 551, 552, 561, 560, 552, 553, 562, 561, 553, 554, 563, 562, 554, 555, 564, 563, 555, 556, 565, 564, 556, 44, 55, 565, 275, 557, 566, 264, 557, 558, 567, 566, 558, 559, 568, 567, 559, 560, 569, 568, 560, 561, 570, 569, 561, 562, 571, 570, 562, 563, 572, 571, 563, 564, 573, 572, 564, 565, 574, 573, 565, 55, 66, 574, 264, 566, 575, 253, 566, 567, 576, 575, 567, 568, 577, 576, 568, 569, 578, 577, 569, 570, 579, 578, 570, 571, 580, 579, 571, 572, 581, 580, 572, 573, 582, 581, 573, 574, 583, 582, 574, 66, 77, 583, 253, 575, 584, 242, 575, 576, 585, 584, 576, 577, 586, 585, 577, 578, 587, 586, 578, 579, 588, 587, 579, 580, 589, 588, 580, 581, 590, 589, 581, 582, 591, 590, 582, 583, 592, 591, 583, 77, 88, 592, 242, 584, 593, 231, 584, 585, 594, 593, 585, 586, 595, 594, 586, 587, 596, 595, 587, 588, 597, 596, 588, 589, 598, 597, 589, 590, 599, 598, 590, 591, 600, 599, 591, 592, 601, 600, 592, 88, 99, 601, 231, 593, 209, 220, 593, 594, 198, 209, 594, 595, 187, 198, 595, 596, 176, 187, 596, 597, 165, 176, 597, 598, 154, 165, 598, 599, 143, 154, 599, 600, 132, 143, 600, 601, 121, 132, 601, 99, 110, 121] + point3f[] points = [(-0.5, -0.5, 0.5), (-0.4, -0.5, 0.5), (-0.3, -0.5, 0.5), (-0.20000002, -0.5, 0.5), (-0.10000002, -0.5, 0.5), (-1.4901161e-8, -0.5, 0.5), (0.09999999, -0.5, 0.5), (0.19999999, -0.5, 0.5), (0.29999998, -0.5, 0.5), (0.39999998, -0.5, 0.5), (0.49999997, -0.5, 0.5), (-0.5, -0.4, 0.5), (-0.4, -0.4, 0.5), (-0.3, -0.4, 0.5), (-0.20000002, -0.4, 0.5), (-0.10000002, -0.4, 0.5), (-1.4901161e-8, -0.4, 0.5), (0.09999999, -0.4, 0.5), (0.19999999, -0.4, 0.5), (0.29999998, -0.4, 0.5), (0.39999998, -0.4, 0.5), (0.49999997, -0.4, 0.5), (-0.5, -0.3, 0.5), (-0.4, -0.3, 0.5), (-0.3, -0.3, 0.5), (-0.20000002, -0.3, 0.5), (-0.10000002, -0.3, 0.5), (-1.4901161e-8, -0.3, 0.5), (0.09999999, -0.3, 0.5), (0.19999999, -0.3, 0.5), (0.29999998, -0.3, 0.5), (0.39999998, -0.3, 0.5), (0.49999997, -0.3, 0.5), (-0.5, -0.20000002, 0.5), (-0.4, -0.20000002, 0.5), (-0.3, -0.20000002, 0.5), (-0.20000002, -0.20000002, 0.5), (-0.10000002, -0.20000002, 0.5), (-1.4901161e-8, -0.20000002, 0.5), (0.09999999, -0.20000002, 0.5), (0.19999999, -0.20000002, 0.5), (0.29999998, -0.20000002, 0.5), (0.39999998, -0.20000002, 0.5), (0.49999997, -0.20000002, 0.5), (-0.5, -0.10000002, 0.5), (-0.4, -0.10000002, 0.5), (-0.3, -0.10000002, 0.5), (-0.20000002, -0.10000002, 0.5), (-0.10000002, -0.10000002, 0.5), (-1.4901161e-8, -0.10000002, 0.5), (0.09999999, -0.10000002, 0.5), (0.19999999, -0.10000002, 0.5), (0.29999998, -0.10000002, 0.5), (0.39999998, -0.10000002, 0.5), (0.49999997, -0.10000002, 0.5), (-0.5, -1.4901161e-8, 0.5), (-0.4, -1.4901161e-8, 0.5), (-0.3, -1.4901161e-8, 0.5), (-0.20000002, -1.4901161e-8, 0.5), (-0.10000002, -1.4901161e-8, 0.5), (-1.4901161e-8, -1.4901161e-8, 0.5), (0.09999999, -1.4901161e-8, 0.5), (0.19999999, -1.4901161e-8, 0.5), (0.29999998, -1.4901161e-8, 0.5), (0.39999998, -1.4901161e-8, 0.5), (0.49999997, -1.4901161e-8, 0.5), (-0.5, 0.09999999, 0.5), (-0.4, 0.09999999, 0.5), (-0.3, 0.09999999, 0.5), (-0.20000002, 0.09999999, 0.5), (-0.10000002, 0.09999999, 0.5), (-1.4901161e-8, 0.09999999, 0.5), (0.09999999, 0.09999999, 0.5), (0.19999999, 0.09999999, 0.5), (0.29999998, 0.09999999, 0.5), (0.39999998, 0.09999999, 0.5), (0.49999997, 0.09999999, 0.5), (-0.5, 0.19999999, 0.5), (-0.4, 0.19999999, 0.5), (-0.3, 0.19999999, 0.5), (-0.20000002, 0.19999999, 0.5), (-0.10000002, 0.19999999, 0.5), (-1.4901161e-8, 0.19999999, 0.5), (0.09999999, 0.19999999, 0.5), (0.19999999, 0.19999999, 0.5), (0.29999998, 0.19999999, 0.5), (0.39999998, 0.19999999, 0.5), (0.49999997, 0.19999999, 0.5), (-0.5, 0.29999998, 0.5), (-0.4, 0.29999998, 0.5), (-0.3, 0.29999998, 0.5), (-0.20000002, 0.29999998, 0.5), (-0.10000002, 0.29999998, 0.5), (-1.4901161e-8, 0.29999998, 0.5), (0.09999999, 0.29999998, 0.5), (0.19999999, 0.29999998, 0.5), (0.29999998, 0.29999998, 0.5), (0.39999998, 0.29999998, 0.5), (0.49999997, 0.29999998, 0.5), (-0.5, 0.39999998, 0.5), (-0.4, 0.39999998, 0.5), (-0.3, 0.39999998, 0.5), (-0.20000002, 0.39999998, 0.5), (-0.10000002, 0.39999998, 0.5), (-1.4901161e-8, 0.39999998, 0.5), (0.09999999, 0.39999998, 0.5), (0.19999999, 0.39999998, 0.5), (0.29999998, 0.39999998, 0.5), (0.39999998, 0.39999998, 0.5), (0.49999997, 0.39999998, 0.5), (-0.5, 0.5, 0.5), (-0.4, 0.5, 0.5), (-0.3, 0.5, 0.5), (-0.20000002, 0.5, 0.5), (-0.10000002, 0.5, 0.5), (-1.4901161e-8, 0.5, 0.5), (0.09999999, 0.5, 0.5), (0.19999999, 0.5, 0.5), (0.29999998, 0.5, 0.5), (0.39999998, 0.5, 0.5), (0.49999997, 0.5, 0.5), (-0.5, 0.5, 0.4), (-0.4, 0.5, 0.4), (-0.3, 0.5, 0.4), (-0.20000002, 0.5, 0.4), (-0.10000002, 0.5, 0.4), (-1.4901161e-8, 0.5, 0.4), (0.09999999, 0.5, 0.4), (0.19999999, 0.5, 0.4), (0.29999998, 0.5, 0.4), (0.39999998, 0.5, 0.4), (0.49999997, 0.5, 0.4), (-0.5, 0.5, 0.3), (-0.4, 0.5, 0.3), (-0.3, 0.5, 0.3), (-0.20000002, 0.5, 0.3), (-0.10000002, 0.5, 0.3), (-1.4901161e-8, 0.5, 0.3), (0.09999999, 0.5, 0.3), (0.19999999, 0.5, 0.3), (0.29999998, 0.5, 0.3), (0.39999998, 0.5, 0.3), (0.49999997, 0.5, 0.3), (-0.5, 0.5, 0.20000002), (-0.4, 0.5, 0.20000002), (-0.3, 0.5, 0.20000002), (-0.20000002, 0.5, 0.20000002), (-0.10000002, 0.5, 0.20000002), (-1.4901161e-8, 0.5, 0.20000002), (0.09999999, 0.5, 0.20000002), (0.19999999, 0.5, 0.20000002), (0.29999998, 0.5, 0.20000002), (0.39999998, 0.5, 0.20000002), (0.49999997, 0.5, 0.20000002), (-0.5, 0.5, 0.10000002), (-0.4, 0.5, 0.10000002), (-0.3, 0.5, 0.10000002), (-0.20000002, 0.5, 0.10000002), (-0.10000002, 0.5, 0.10000002), (-1.4901161e-8, 0.5, 0.10000002), (0.09999999, 0.5, 0.10000002), (0.19999999, 0.5, 0.10000002), (0.29999998, 0.5, 0.10000002), (0.39999998, 0.5, 0.10000002), (0.49999997, 0.5, 0.10000002), (-0.5, 0.5, 1.4901161e-8), (-0.4, 0.5, 1.4901161e-8), (-0.3, 0.5, 1.4901161e-8), (-0.20000002, 0.5, 1.4901161e-8), (-0.10000002, 0.5, 1.4901161e-8), (-1.4901161e-8, 0.5, 1.4901161e-8), (0.09999999, 0.5, 1.4901161e-8), (0.19999999, 0.5, 1.4901161e-8), (0.29999998, 0.5, 1.4901161e-8), (0.39999998, 0.5, 1.4901161e-8), (0.49999997, 0.5, 1.4901161e-8), (-0.5, 0.5, -0.09999999), (-0.4, 0.5, -0.09999999), (-0.3, 0.5, -0.09999999), (-0.20000002, 0.5, -0.09999999), (-0.10000002, 0.5, -0.09999999), (-1.4901161e-8, 0.5, -0.09999999), (0.09999999, 0.5, -0.09999999), (0.19999999, 0.5, -0.09999999), (0.29999998, 0.5, -0.09999999), (0.39999998, 0.5, -0.09999999), (0.49999997, 0.5, -0.09999999), (-0.5, 0.5, -0.19999999), (-0.4, 0.5, -0.19999999), (-0.3, 0.5, -0.19999999), (-0.20000002, 0.5, -0.19999999), (-0.10000002, 0.5, -0.19999999), (-1.4901161e-8, 0.5, -0.19999999), (0.09999999, 0.5, -0.19999999), (0.19999999, 0.5, -0.19999999), (0.29999998, 0.5, -0.19999999), (0.39999998, 0.5, -0.19999999), (0.49999997, 0.5, -0.19999999), (-0.5, 0.5, -0.29999998), (-0.4, 0.5, -0.29999998), (-0.3, 0.5, -0.29999998), (-0.20000002, 0.5, -0.29999998), (-0.10000002, 0.5, -0.29999998), (-1.4901161e-8, 0.5, -0.29999998), (0.09999999, 0.5, -0.29999998), (0.19999999, 0.5, -0.29999998), (0.29999998, 0.5, -0.29999998), (0.39999998, 0.5, -0.29999998), (0.49999997, 0.5, -0.29999998), (-0.5, 0.5, -0.39999998), (-0.4, 0.5, -0.39999998), (-0.3, 0.5, -0.39999998), (-0.20000002, 0.5, -0.39999998), (-0.10000002, 0.5, -0.39999998), (-1.4901161e-8, 0.5, -0.39999998), (0.09999999, 0.5, -0.39999998), (0.19999999, 0.5, -0.39999998), (0.29999998, 0.5, -0.39999998), (0.39999998, 0.5, -0.39999998), (0.49999997, 0.5, -0.39999998), (-0.5, 0.5, -0.5), (-0.4, 0.5, -0.5), (-0.3, 0.5, -0.5), (-0.20000002, 0.5, -0.5), (-0.10000002, 0.5, -0.5), (-1.4901161e-8, 0.5, -0.5), (0.09999999, 0.5, -0.5), (0.19999999, 0.5, -0.5), (0.29999998, 0.5, -0.5), (0.39999998, 0.5, -0.5), (0.49999997, 0.5, -0.5), (-0.5, 0.4, -0.5), (-0.4, 0.4, -0.5), (-0.3, 0.4, -0.5), (-0.20000002, 0.4, -0.5), (-0.10000002, 0.4, -0.5), (-1.4901161e-8, 0.4, -0.5), (0.09999999, 0.4, -0.5), (0.19999999, 0.4, -0.5), (0.29999998, 0.4, -0.5), (0.39999998, 0.4, -0.5), (0.49999997, 0.4, -0.5), (-0.5, 0.3, -0.5), (-0.4, 0.3, -0.5), (-0.3, 0.3, -0.5), (-0.20000002, 0.3, -0.5), (-0.10000002, 0.3, -0.5), (-1.4901161e-8, 0.3, -0.5), (0.09999999, 0.3, -0.5), (0.19999999, 0.3, -0.5), (0.29999998, 0.3, -0.5), (0.39999998, 0.3, -0.5), (0.49999997, 0.3, -0.5), (-0.5, 0.20000002, -0.5), (-0.4, 0.20000002, -0.5), (-0.3, 0.20000002, -0.5), (-0.20000002, 0.20000002, -0.5), (-0.10000002, 0.20000002, -0.5), (-1.4901161e-8, 0.20000002, -0.5), (0.09999999, 0.20000002, -0.5), (0.19999999, 0.20000002, -0.5), (0.29999998, 0.20000002, -0.5), (0.39999998, 0.20000002, -0.5), (0.49999997, 0.20000002, -0.5), (-0.5, 0.10000002, -0.5), (-0.4, 0.10000002, -0.5), (-0.3, 0.10000002, -0.5), (-0.20000002, 0.10000002, -0.5), (-0.10000002, 0.10000002, -0.5), (-1.4901161e-8, 0.10000002, -0.5), (0.09999999, 0.10000002, -0.5), (0.19999999, 0.10000002, -0.5), (0.29999998, 0.10000002, -0.5), (0.39999998, 0.10000002, -0.5), (0.49999997, 0.10000002, -0.5), (-0.5, 1.4901161e-8, -0.5), (-0.4, 1.4901161e-8, -0.5), (-0.3, 1.4901161e-8, -0.5), (-0.20000002, 1.4901161e-8, -0.5), (-0.10000002, 1.4901161e-8, -0.5), (-1.4901161e-8, 1.4901161e-8, -0.5), (0.09999999, 1.4901161e-8, -0.5), (0.19999999, 1.4901161e-8, -0.5), (0.29999998, 1.4901161e-8, -0.5), (0.39999998, 1.4901161e-8, -0.5), (0.49999997, 1.4901161e-8, -0.5), (-0.5, -0.09999999, -0.5), (-0.4, -0.09999999, -0.5), (-0.3, -0.09999999, -0.5), (-0.20000002, -0.09999999, -0.5), (-0.10000002, -0.09999999, -0.5), (-1.4901161e-8, -0.09999999, -0.5), (0.09999999, -0.09999999, -0.5), (0.19999999, -0.09999999, -0.5), (0.29999998, -0.09999999, -0.5), (0.39999998, -0.09999999, -0.5), (0.49999997, -0.09999999, -0.5), (-0.5, -0.19999999, -0.5), (-0.4, -0.19999999, -0.5), (-0.3, -0.19999999, -0.5), (-0.20000002, -0.19999999, -0.5), (-0.10000002, -0.19999999, -0.5), (-1.4901161e-8, -0.19999999, -0.5), (0.09999999, -0.19999999, -0.5), (0.19999999, -0.19999999, -0.5), (0.29999998, -0.19999999, -0.5), (0.39999998, -0.19999999, -0.5), (0.49999997, -0.19999999, -0.5), (-0.5, -0.29999998, -0.5), (-0.4, -0.29999998, -0.5), (-0.3, -0.29999998, -0.5), (-0.20000002, -0.29999998, -0.5), (-0.10000002, -0.29999998, -0.5), (-1.4901161e-8, -0.29999998, -0.5), (0.09999999, -0.29999998, -0.5), (0.19999999, -0.29999998, -0.5), (0.29999998, -0.29999998, -0.5), (0.39999998, -0.29999998, -0.5), (0.49999997, -0.29999998, -0.5), (-0.5, -0.39999998, -0.5), (-0.4, -0.39999998, -0.5), (-0.3, -0.39999998, -0.5), (-0.20000002, -0.39999998, -0.5), (-0.10000002, -0.39999998, -0.5), (-1.4901161e-8, -0.39999998, -0.5), (0.09999999, -0.39999998, -0.5), (0.19999999, -0.39999998, -0.5), (0.29999998, -0.39999998, -0.5), (0.39999998, -0.39999998, -0.5), (0.49999997, -0.39999998, -0.5), (-0.5, -0.5, -0.5), (-0.4, -0.5, -0.5), (-0.3, -0.5, -0.5), (-0.20000002, -0.5, -0.5), (-0.10000002, -0.5, -0.5), (-1.4901161e-8, -0.5, -0.5), (0.09999999, -0.5, -0.5), (0.19999999, -0.5, -0.5), (0.29999998, -0.5, -0.5), (0.39999998, -0.5, -0.5), (0.49999997, -0.5, -0.5), (-0.5, -0.5, -0.4), (-0.4, -0.5, -0.4), (-0.3, -0.5, -0.4), (-0.20000002, -0.5, -0.4), (-0.10000002, -0.5, -0.4), (-1.4901161e-8, -0.5, -0.4), (0.09999999, -0.5, -0.4), (0.19999999, -0.5, -0.4), (0.29999998, -0.5, -0.4), (0.39999998, -0.5, -0.4), (0.49999997, -0.5, -0.4), (-0.5, -0.5, -0.3), (-0.4, -0.5, -0.3), (-0.3, -0.5, -0.3), (-0.20000002, -0.5, -0.3), (-0.10000002, -0.5, -0.3), (-1.4901161e-8, -0.5, -0.3), (0.09999999, -0.5, -0.3), (0.19999999, -0.5, -0.3), (0.29999998, -0.5, -0.3), (0.39999998, -0.5, -0.3), (0.49999997, -0.5, -0.3), (-0.5, -0.5, -0.20000002), (-0.4, -0.5, -0.20000002), (-0.3, -0.5, -0.20000002), (-0.20000002, -0.5, -0.20000002), (-0.10000002, -0.5, -0.20000002), (-1.4901161e-8, -0.5, -0.20000002), (0.09999999, -0.5, -0.20000002), (0.19999999, -0.5, -0.20000002), (0.29999998, -0.5, -0.20000002), (0.39999998, -0.5, -0.20000002), (0.49999997, -0.5, -0.20000002), (-0.5, -0.5, -0.10000002), (-0.4, -0.5, -0.10000002), (-0.3, -0.5, -0.10000002), (-0.20000002, -0.5, -0.10000002), (-0.10000002, -0.5, -0.10000002), (-1.4901161e-8, -0.5, -0.10000002), (0.09999999, -0.5, -0.10000002), (0.19999999, -0.5, -0.10000002), (0.29999998, -0.5, -0.10000002), (0.39999998, -0.5, -0.10000002), (0.49999997, -0.5, -0.10000002), (-0.5, -0.5, -1.4901161e-8), (-0.4, -0.5, -1.4901161e-8), (-0.3, -0.5, -1.4901161e-8), (-0.20000002, -0.5, -1.4901161e-8), (-0.10000002, -0.5, -1.4901161e-8), (-1.4901161e-8, -0.5, -1.4901161e-8), (0.09999999, -0.5, -1.4901161e-8), (0.19999999, -0.5, -1.4901161e-8), (0.29999998, -0.5, -1.4901161e-8), (0.39999998, -0.5, -1.4901161e-8), (0.49999997, -0.5, -1.4901161e-8), (-0.5, -0.5, 0.09999999), (-0.4, -0.5, 0.09999999), (-0.3, -0.5, 0.09999999), (-0.20000002, -0.5, 0.09999999), (-0.10000002, -0.5, 0.09999999), (-1.4901161e-8, -0.5, 0.09999999), (0.09999999, -0.5, 0.09999999), (0.19999999, -0.5, 0.09999999), (0.29999998, -0.5, 0.09999999), (0.39999998, -0.5, 0.09999999), (0.49999997, -0.5, 0.09999999), (-0.5, -0.5, 0.19999999), (-0.4, -0.5, 0.19999999), (-0.3, -0.5, 0.19999999), (-0.20000002, -0.5, 0.19999999), (-0.10000002, -0.5, 0.19999999), (-1.4901161e-8, -0.5, 0.19999999), (0.09999999, -0.5, 0.19999999), (0.19999999, -0.5, 0.19999999), (0.29999998, -0.5, 0.19999999), (0.39999998, -0.5, 0.19999999), (0.49999997, -0.5, 0.19999999), (-0.5, -0.5, 0.29999998), (-0.4, -0.5, 0.29999998), (-0.3, -0.5, 0.29999998), (-0.20000002, -0.5, 0.29999998), (-0.10000002, -0.5, 0.29999998), (-1.4901161e-8, -0.5, 0.29999998), (0.09999999, -0.5, 0.29999998), (0.19999999, -0.5, 0.29999998), (0.29999998, -0.5, 0.29999998), (0.39999998, -0.5, 0.29999998), (0.49999997, -0.5, 0.29999998), (-0.5, -0.5, 0.39999998), (-0.4, -0.5, 0.39999998), (-0.3, -0.5, 0.39999998), (-0.20000002, -0.5, 0.39999998), (-0.10000002, -0.5, 0.39999998), (-1.4901161e-8, -0.5, 0.39999998), (0.09999999, -0.5, 0.39999998), (0.19999999, -0.5, 0.39999998), (0.29999998, -0.5, 0.39999998), (0.39999998, -0.5, 0.39999998), (0.49999997, -0.5, 0.39999998), (0.5, -0.4, -0.4), (0.5, -0.4, -0.3), (0.5, -0.4, -0.20000002), (0.5, -0.4, -0.10000002), (0.5, -0.4, -1.4901161e-8), (0.5, -0.4, 0.09999999), (0.5, -0.4, 0.19999999), (0.5, -0.4, 0.29999998), (0.5, -0.4, 0.39999998), (0.5, -0.3, -0.4), (0.5, -0.3, -0.3), (0.5, -0.3, -0.20000002), (0.5, -0.3, -0.10000002), (0.5, -0.3, -1.4901161e-8), (0.5, -0.3, 0.09999999), (0.5, -0.3, 0.19999999), (0.5, -0.3, 0.29999998), (0.5, -0.3, 0.39999998), (0.5, -0.20000002, -0.4), (0.5, -0.20000002, -0.3), (0.5, -0.20000002, -0.20000002), (0.5, -0.20000002, -0.10000002), (0.5, -0.20000002, -1.4901161e-8), (0.5, -0.20000002, 0.09999999), (0.5, -0.20000002, 0.19999999), (0.5, -0.20000002, 0.29999998), (0.5, -0.20000002, 0.39999998), (0.5, -0.10000002, -0.4), (0.5, -0.10000002, -0.3), (0.5, -0.10000002, -0.20000002), (0.5, -0.10000002, -0.10000002), (0.5, -0.10000002, -1.4901161e-8), (0.5, -0.10000002, 0.09999999), (0.5, -0.10000002, 0.19999999), (0.5, -0.10000002, 0.29999998), (0.5, -0.10000002, 0.39999998), (0.5, -1.4901161e-8, -0.4), (0.5, -1.4901161e-8, -0.3), (0.5, -1.4901161e-8, -0.20000002), (0.5, -1.4901161e-8, -0.10000002), (0.5, -1.4901161e-8, -1.4901161e-8), (0.5, -1.4901161e-8, 0.09999999), (0.5, -1.4901161e-8, 0.19999999), (0.5, -1.4901161e-8, 0.29999998), (0.5, -1.4901161e-8, 0.39999998), (0.5, 0.09999999, -0.4), (0.5, 0.09999999, -0.3), (0.5, 0.09999999, -0.20000002), (0.5, 0.09999999, -0.10000002), (0.5, 0.09999999, -1.4901161e-8), (0.5, 0.09999999, 0.09999999), (0.5, 0.09999999, 0.19999999), (0.5, 0.09999999, 0.29999998), (0.5, 0.09999999, 0.39999998), (0.5, 0.19999999, -0.4), (0.5, 0.19999999, -0.3), (0.5, 0.19999999, -0.20000002), (0.5, 0.19999999, -0.10000002), (0.5, 0.19999999, -1.4901161e-8), (0.5, 0.19999999, 0.09999999), (0.5, 0.19999999, 0.19999999), (0.5, 0.19999999, 0.29999998), (0.5, 0.19999999, 0.39999998), (0.5, 0.29999998, -0.4), (0.5, 0.29999998, -0.3), (0.5, 0.29999998, -0.20000002), (0.5, 0.29999998, -0.10000002), (0.5, 0.29999998, -1.4901161e-8), (0.5, 0.29999998, 0.09999999), (0.5, 0.29999998, 0.19999999), (0.5, 0.29999998, 0.29999998), (0.5, 0.29999998, 0.39999998), (0.5, 0.39999998, -0.4), (0.5, 0.39999998, -0.3), (0.5, 0.39999998, -0.20000002), (0.5, 0.39999998, -0.10000002), (0.5, 0.39999998, -1.4901161e-8), (0.5, 0.39999998, 0.09999999), (0.5, 0.39999998, 0.19999999), (0.5, 0.39999998, 0.29999998), (0.5, 0.39999998, 0.39999998), (-0.5, -0.4, -0.4), (-0.5, -0.4, -0.3), (-0.5, -0.4, -0.20000002), (-0.5, -0.4, -0.10000002), (-0.5, -0.4, -1.4901161e-8), (-0.5, -0.4, 0.09999999), (-0.5, -0.4, 0.19999999), (-0.5, -0.4, 0.29999998), (-0.5, -0.4, 0.39999998), (-0.5, -0.3, -0.4), (-0.5, -0.3, -0.3), (-0.5, -0.3, -0.20000002), (-0.5, -0.3, -0.10000002), (-0.5, -0.3, -1.4901161e-8), (-0.5, -0.3, 0.09999999), (-0.5, -0.3, 0.19999999), (-0.5, -0.3, 0.29999998), (-0.5, -0.3, 0.39999998), (-0.5, -0.20000002, -0.4), (-0.5, -0.20000002, -0.3), (-0.5, -0.20000002, -0.20000002), (-0.5, -0.20000002, -0.10000002), (-0.5, -0.20000002, -1.4901161e-8), (-0.5, -0.20000002, 0.09999999), (-0.5, -0.20000002, 0.19999999), (-0.5, -0.20000002, 0.29999998), (-0.5, -0.20000002, 0.39999998), (-0.5, -0.10000002, -0.4), (-0.5, -0.10000002, -0.3), (-0.5, -0.10000002, -0.20000002), (-0.5, -0.10000002, -0.10000002), (-0.5, -0.10000002, -1.4901161e-8), (-0.5, -0.10000002, 0.09999999), (-0.5, -0.10000002, 0.19999999), (-0.5, -0.10000002, 0.29999998), (-0.5, -0.10000002, 0.39999998), (-0.5, -1.4901161e-8, -0.4), (-0.5, -1.4901161e-8, -0.3), (-0.5, -1.4901161e-8, -0.20000002), (-0.5, -1.4901161e-8, -0.10000002), (-0.5, -1.4901161e-8, -1.4901161e-8), (-0.5, -1.4901161e-8, 0.09999999), (-0.5, -1.4901161e-8, 0.19999999), (-0.5, -1.4901161e-8, 0.29999998), (-0.5, -1.4901161e-8, 0.39999998), (-0.5, 0.09999999, -0.4), (-0.5, 0.09999999, -0.3), (-0.5, 0.09999999, -0.20000002), (-0.5, 0.09999999, -0.10000002), (-0.5, 0.09999999, -1.4901161e-8), (-0.5, 0.09999999, 0.09999999), (-0.5, 0.09999999, 0.19999999), (-0.5, 0.09999999, 0.29999998), (-0.5, 0.09999999, 0.39999998), (-0.5, 0.19999999, -0.4), (-0.5, 0.19999999, -0.3), (-0.5, 0.19999999, -0.20000002), (-0.5, 0.19999999, -0.10000002), (-0.5, 0.19999999, -1.4901161e-8), (-0.5, 0.19999999, 0.09999999), (-0.5, 0.19999999, 0.19999999), (-0.5, 0.19999999, 0.29999998), (-0.5, 0.19999999, 0.39999998), (-0.5, 0.29999998, -0.4), (-0.5, 0.29999998, -0.3), (-0.5, 0.29999998, -0.20000002), (-0.5, 0.29999998, -0.10000002), (-0.5, 0.29999998, -1.4901161e-8), (-0.5, 0.29999998, 0.09999999), (-0.5, 0.29999998, 0.19999999), (-0.5, 0.29999998, 0.29999998), (-0.5, 0.29999998, 0.39999998), (-0.5, 0.39999998, -0.4), (-0.5, 0.39999998, -0.3), (-0.5, 0.39999998, -0.20000002), (-0.5, 0.39999998, -0.10000002), (-0.5, 0.39999998, -1.4901161e-8), (-0.5, 0.39999998, 0.09999999), (-0.5, 0.39999998, 0.19999999), (-0.5, 0.39999998, 0.29999998), (-0.5, 0.39999998, 0.39999998)] + + def GeomSubset "CubeUpperHalf" + { + uniform token elementType = "face" + int[] indices = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599] + } +} + diff --git a/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetSphere.usda b/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetSphere.usda new file mode 100644 index 0000000000..61c96ee3fc --- /dev/null +++ b/test/testSamples/testGeomSubsetsPicking/UpperHalfGeomSubsetSphere.usda @@ -0,0 +1,24 @@ +#usda 1.0 +( + defaultPrim = "UpperHalfGeomSubsetSphere" + metersPerUnit = 0.01 + upAxis = "Z" +) + +def Mesh "UpperHalfGeomSubsetSphere" ( + kind = "component" +) +{ + uniform bool doubleSided = 1 + float3[] extent = [(-1, -1, -1), (1, 1, 1)] + int[] faceVertexCounts = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] + int[] faceVertexIndices = [0, 1, 21, 20, 1, 2, 22, 21, 2, 3, 23, 22, 3, 4, 24, 23, 4, 5, 25, 24, 5, 6, 26, 25, 6, 7, 27, 26, 7, 8, 28, 27, 8, 9, 29, 28, 9, 10, 30, 29, 10, 11, 31, 30, 11, 12, 32, 31, 12, 13, 33, 32, 13, 14, 34, 33, 14, 15, 35, 34, 15, 16, 36, 35, 16, 17, 37, 36, 17, 18, 38, 37, 18, 19, 39, 38, 19, 0, 20, 39, 20, 21, 41, 40, 21, 22, 42, 41, 22, 23, 43, 42, 23, 24, 44, 43, 24, 25, 45, 44, 25, 26, 46, 45, 26, 27, 47, 46, 27, 28, 48, 47, 28, 29, 49, 48, 29, 30, 50, 49, 30, 31, 51, 50, 31, 32, 52, 51, 32, 33, 53, 52, 33, 34, 54, 53, 34, 35, 55, 54, 35, 36, 56, 55, 36, 37, 57, 56, 37, 38, 58, 57, 38, 39, 59, 58, 39, 20, 40, 59, 40, 41, 61, 60, 41, 42, 62, 61, 42, 43, 63, 62, 43, 44, 64, 63, 44, 45, 65, 64, 45, 46, 66, 65, 46, 47, 67, 66, 47, 48, 68, 67, 48, 49, 69, 68, 49, 50, 70, 69, 50, 51, 71, 70, 51, 52, 72, 71, 52, 53, 73, 72, 53, 54, 74, 73, 54, 55, 75, 74, 55, 56, 76, 75, 56, 57, 77, 76, 57, 58, 78, 77, 58, 59, 79, 78, 59, 40, 60, 79, 60, 61, 81, 80, 61, 62, 82, 81, 62, 63, 83, 82, 63, 64, 84, 83, 64, 65, 85, 84, 65, 66, 86, 85, 66, 67, 87, 86, 67, 68, 88, 87, 68, 69, 89, 88, 69, 70, 90, 89, 70, 71, 91, 90, 71, 72, 92, 91, 72, 73, 93, 92, 73, 74, 94, 93, 74, 75, 95, 94, 75, 76, 96, 95, 76, 77, 97, 96, 77, 78, 98, 97, 78, 79, 99, 98, 79, 60, 80, 99, 80, 81, 101, 100, 81, 82, 102, 101, 82, 83, 103, 102, 83, 84, 104, 103, 84, 85, 105, 104, 85, 86, 106, 105, 86, 87, 107, 106, 87, 88, 108, 107, 88, 89, 109, 108, 89, 90, 110, 109, 90, 91, 111, 110, 91, 92, 112, 111, 92, 93, 113, 112, 93, 94, 114, 113, 94, 95, 115, 114, 95, 96, 116, 115, 96, 97, 117, 116, 97, 98, 118, 117, 98, 99, 119, 118, 99, 80, 100, 119, 100, 101, 121, 120, 101, 102, 122, 121, 102, 103, 123, 122, 103, 104, 124, 123, 104, 105, 125, 124, 105, 106, 126, 125, 106, 107, 127, 126, 107, 108, 128, 127, 108, 109, 129, 128, 109, 110, 130, 129, 110, 111, 131, 130, 111, 112, 132, 131, 112, 113, 133, 132, 113, 114, 134, 133, 114, 115, 135, 134, 115, 116, 136, 135, 116, 117, 137, 136, 117, 118, 138, 137, 118, 119, 139, 138, 119, 100, 120, 139, 120, 121, 141, 140, 121, 122, 142, 141, 122, 123, 143, 142, 123, 124, 144, 143, 124, 125, 145, 144, 125, 126, 146, 145, 126, 127, 147, 146, 127, 128, 148, 147, 128, 129, 149, 148, 129, 130, 150, 149, 130, 131, 151, 150, 131, 132, 152, 151, 132, 133, 153, 152, 133, 134, 154, 153, 134, 135, 155, 154, 135, 136, 156, 155, 136, 137, 157, 156, 137, 138, 158, 157, 138, 139, 159, 158, 139, 120, 140, 159, 140, 141, 161, 160, 141, 142, 162, 161, 142, 143, 163, 162, 143, 144, 164, 163, 144, 145, 165, 164, 145, 146, 166, 165, 146, 147, 167, 166, 147, 148, 168, 167, 148, 149, 169, 168, 149, 150, 170, 169, 150, 151, 171, 170, 151, 152, 172, 171, 152, 153, 173, 172, 153, 154, 174, 173, 154, 155, 175, 174, 155, 156, 176, 175, 156, 157, 177, 176, 157, 158, 178, 177, 158, 159, 179, 178, 159, 140, 160, 179, 160, 161, 181, 180, 161, 162, 182, 181, 162, 163, 183, 182, 163, 164, 184, 183, 164, 165, 185, 184, 165, 166, 186, 185, 166, 167, 187, 186, 167, 168, 188, 187, 168, 169, 189, 188, 169, 170, 190, 189, 170, 171, 191, 190, 171, 172, 192, 191, 172, 173, 193, 192, 173, 174, 194, 193, 174, 175, 195, 194, 175, 176, 196, 195, 176, 177, 197, 196, 177, 178, 198, 197, 178, 179, 199, 198, 179, 160, 180, 199, 180, 181, 201, 200, 181, 182, 202, 201, 182, 183, 203, 202, 183, 184, 204, 203, 184, 185, 205, 204, 185, 186, 206, 205, 186, 187, 207, 206, 187, 188, 208, 207, 188, 189, 209, 208, 189, 190, 210, 209, 190, 191, 211, 210, 191, 192, 212, 211, 192, 193, 213, 212, 193, 194, 214, 213, 194, 195, 215, 214, 195, 196, 216, 215, 196, 197, 217, 216, 197, 198, 218, 217, 198, 199, 219, 218, 199, 180, 200, 219, 200, 201, 221, 220, 201, 202, 222, 221, 202, 203, 223, 222, 203, 204, 224, 223, 204, 205, 225, 224, 205, 206, 226, 225, 206, 207, 227, 226, 207, 208, 228, 227, 208, 209, 229, 228, 209, 210, 230, 229, 210, 211, 231, 230, 211, 212, 232, 231, 212, 213, 233, 232, 213, 214, 234, 233, 214, 215, 235, 234, 215, 216, 236, 235, 216, 217, 237, 236, 217, 218, 238, 237, 218, 219, 239, 238, 219, 200, 220, 239, 220, 221, 241, 240, 221, 222, 242, 241, 222, 223, 243, 242, 223, 224, 244, 243, 224, 225, 245, 244, 225, 226, 246, 245, 226, 227, 247, 246, 227, 228, 248, 247, 228, 229, 249, 248, 229, 230, 250, 249, 230, 231, 251, 250, 231, 232, 252, 251, 232, 233, 253, 252, 233, 234, 254, 253, 234, 235, 255, 254, 235, 236, 256, 255, 236, 237, 257, 256, 237, 238, 258, 257, 238, 239, 259, 258, 239, 220, 240, 259, 240, 241, 261, 260, 241, 242, 262, 261, 242, 243, 263, 262, 243, 244, 264, 263, 244, 245, 265, 264, 245, 246, 266, 265, 246, 247, 267, 266, 247, 248, 268, 267, 248, 249, 269, 268, 249, 250, 270, 269, 250, 251, 271, 270, 251, 252, 272, 271, 252, 253, 273, 272, 253, 254, 274, 273, 254, 255, 275, 274, 255, 256, 276, 275, 256, 257, 277, 276, 257, 258, 278, 277, 258, 259, 279, 278, 259, 240, 260, 279, 260, 261, 281, 280, 261, 262, 282, 281, 262, 263, 283, 282, 263, 264, 284, 283, 264, 265, 285, 284, 265, 266, 286, 285, 266, 267, 287, 286, 267, 268, 288, 287, 268, 269, 289, 288, 269, 270, 290, 289, 270, 271, 291, 290, 271, 272, 292, 291, 272, 273, 293, 292, 273, 274, 294, 293, 274, 275, 295, 294, 275, 276, 296, 295, 276, 277, 297, 296, 277, 278, 298, 297, 278, 279, 299, 298, 279, 260, 280, 299, 280, 281, 301, 300, 281, 282, 302, 301, 282, 283, 303, 302, 283, 284, 304, 303, 284, 285, 305, 304, 285, 286, 306, 305, 286, 287, 307, 306, 287, 288, 308, 307, 288, 289, 309, 308, 289, 290, 310, 309, 290, 291, 311, 310, 291, 292, 312, 311, 292, 293, 313, 312, 293, 294, 314, 313, 294, 295, 315, 314, 295, 296, 316, 315, 296, 297, 317, 316, 297, 298, 318, 317, 298, 299, 319, 318, 299, 280, 300, 319, 300, 301, 321, 320, 301, 302, 322, 321, 302, 303, 323, 322, 303, 304, 324, 323, 304, 305, 325, 324, 305, 306, 326, 325, 306, 307, 327, 326, 307, 308, 328, 327, 308, 309, 329, 328, 309, 310, 330, 329, 310, 311, 331, 330, 311, 312, 332, 331, 312, 313, 333, 332, 313, 314, 334, 333, 314, 315, 335, 334, 315, 316, 336, 335, 316, 317, 337, 336, 317, 318, 338, 337, 318, 319, 339, 338, 319, 300, 320, 339, 320, 321, 341, 340, 321, 322, 342, 341, 322, 323, 343, 342, 323, 324, 344, 343, 324, 325, 345, 344, 325, 326, 346, 345, 326, 327, 347, 346, 327, 328, 348, 347, 328, 329, 349, 348, 329, 330, 350, 349, 330, 331, 351, 350, 331, 332, 352, 351, 332, 333, 353, 352, 333, 334, 354, 353, 334, 335, 355, 354, 335, 336, 356, 355, 336, 337, 357, 356, 337, 338, 358, 357, 338, 339, 359, 358, 339, 320, 340, 359, 340, 341, 361, 360, 341, 342, 362, 361, 342, 343, 363, 362, 343, 344, 364, 363, 344, 345, 365, 364, 345, 346, 366, 365, 346, 347, 367, 366, 347, 348, 368, 367, 348, 349, 369, 368, 349, 350, 370, 369, 350, 351, 371, 370, 351, 352, 372, 371, 352, 353, 373, 372, 353, 354, 374, 373, 354, 355, 375, 374, 355, 356, 376, 375, 356, 357, 377, 376, 357, 358, 378, 377, 358, 359, 379, 378, 359, 340, 360, 379, 1, 0, 380, 2, 1, 380, 3, 2, 380, 4, 3, 380, 5, 4, 380, 6, 5, 380, 7, 6, 380, 8, 7, 380, 9, 8, 380, 10, 9, 380, 11, 10, 380, 12, 11, 380, 13, 12, 380, 14, 13, 380, 15, 14, 380, 16, 15, 380, 17, 16, 380, 18, 17, 380, 19, 18, 380, 0, 19, 380, 360, 361, 381, 361, 362, 381, 362, 363, 381, 363, 364, 381, 364, 365, 381, 365, 366, 381, 366, 367, 381, 367, 368, 381, 368, 369, 381, 369, 370, 381, 370, 371, 381, 371, 372, 381, 372, 373, 381, 373, 374, 381, 374, 375, 381, 375, 376, 381, 376, 377, 381, 377, 378, 381, 378, 379, 381, 379, 360, 381] + point3f[] points = [(0.14877813, -0.98768836, -0.048340943), (0.12655823, -0.98768836, -0.09194993), (0.09194993, -0.98768836, -0.12655823), (0.048340935, -0.98768836, -0.14877811), (0, -0.98768836, -0.15643455), (-0.048340935, -0.98768836, -0.1487781), (-0.09194992, -0.98768836, -0.1265582), (-0.12655818, -0.98768836, -0.0919499), (-0.14877807, -0.98768836, -0.048340924), (-0.15643452, -0.98768836, 0), (-0.14877807, -0.98768836, 0.048340924), (-0.12655818, -0.98768836, 0.091949895), (-0.091949895, -0.98768836, 0.12655817), (-0.048340924, -0.98768836, 0.14877805), (-4.6621107e-9, -0.98768836, 0.15643449), (0.04834091, -0.98768836, 0.14877804), (0.09194988, -0.98768836, 0.12655815), (0.12655815, -0.98768836, 0.09194989), (0.14877804, -0.98768836, 0.048340913), (0.15643448, -0.98768836, 0), (0.29389283, -0.95105654, -0.095491566), (0.25000018, -0.95105654, -0.18163574), (0.18163574, -0.95105654, -0.25000015), (0.09549155, -0.95105654, -0.2938928), (0, -0.95105654, -0.30901715), (-0.09549155, -0.95105654, -0.29389277), (-0.18163571, -0.95105654, -0.2500001), (-0.2500001, -0.95105654, -0.1816357), (-0.2938927, -0.95105654, -0.09549153), (-0.30901706, -0.95105654, 0), (-0.2938927, -0.95105654, 0.09549153), (-0.25000006, -0.95105654, 0.18163568), (-0.18163568, -0.95105654, 0.25000006), (-0.09549153, -0.95105654, 0.29389268), (-9.209424e-9, -0.95105654, 0.30901703), (0.0954915, -0.95105654, 0.29389265), (0.18163563, -0.95105654, 0.25000003), (0.25, -0.95105654, 0.18163565), (0.29389265, -0.95105654, 0.095491506), (0.309017, -0.95105654, 0), (0.43177092, -0.8910065, -0.14029087), (0.3672863, -0.8910065, -0.2668491), (0.2668491, -0.8910065, -0.36728626), (0.14029086, -0.8910065, -0.43177086), (0, -0.8910065, -0.45399073), (-0.14029086, -0.8910065, -0.43177083), (-0.26684904, -0.8910065, -0.36728618), (-0.36728615, -0.8910065, -0.266849), (-0.43177077, -0.8910065, -0.14029081), (-0.45399064, -0.8910065, 0), (-0.43177077, -0.8910065, 0.14029081), (-0.36728612, -0.8910065, 0.26684898), (-0.26684898, -0.8910065, 0.36728612), (-0.14029081, -0.8910065, 0.4317707), (-1.3529972e-8, -0.8910065, 0.45399058), (0.14029078, -0.8910065, 0.43177068), (0.26684892, -0.8910065, 0.3672861), (0.36728606, -0.8910065, 0.26684895), (0.43177065, -0.8910065, 0.1402908), (0.45399052, -0.8910065, 0), (0.55901736, -0.809017, -0.18163574), (0.47552857, -0.809017, -0.3454917), (0.3454917, -0.809017, -0.47552854), (0.18163572, -0.809017, -0.5590173), (0, -0.809017, -0.58778554), (-0.18163572, -0.809017, -0.55901724), (-0.34549165, -0.809017, -0.47552842), (-0.4755284, -0.809017, -0.3454916), (-0.5590171, -0.809017, -0.18163566), (-0.58778536, -0.809017, 0), (-0.5590171, -0.809017, 0.18163566), (-0.47552836, -0.809017, 0.34549156), (-0.34549156, -0.809017, 0.47552833), (-0.18163566, -0.809017, 0.55901706), (-1.7517365e-8, -0.809017, 0.5877853), (0.18163562, -0.809017, 0.55901706), (0.3454915, -0.809017, 0.4755283), (0.47552827, -0.809017, 0.34549153), (0.559017, -0.809017, 0.18163563), (0.58778524, -0.809017, 0), (0.67249894, -0.70710677, -0.21850814), (0.5720618, -0.70710677, -0.41562718), (0.41562718, -0.70710677, -0.5720617), (0.21850812, -0.70710677, -0.6724989), (0, -0.70710677, -0.7071071), (-0.21850812, -0.70710677, -0.6724988), (-0.4156271, -0.70710677, -0.5720616), (-0.57206154, -0.70710677, -0.41562706), (-0.6724987, -0.70710677, -0.21850805), (-0.70710695, -0.70710677, 0), (-0.6724987, -0.70710677, 0.21850805), (-0.57206154, -0.70710677, 0.415627), (-0.415627, -0.70710677, 0.5720615), (-0.21850805, -0.70710677, 0.6724986), (-2.1073424e-8, -0.70710677, 0.7071068), (0.21850799, -0.70710677, 0.6724986), (0.4156269, -0.70710677, 0.5720614), (0.5720614, -0.70710677, 0.41562697), (0.6724985, -0.70710677, 0.21850802), (0.70710677, -0.70710677, 0), (0.7694214, -0.58778524, -0.25000015), (0.65450895, -0.58778524, -0.47552854), (0.47552854, -0.58778524, -0.6545089), (0.25000012, -0.58778524, -0.7694213), (0, -0.58778524, -0.80901736), (-0.25000012, -0.58778524, -0.7694212), (-0.47552845, -0.58778524, -0.65450877), (-0.6545087, -0.58778524, -0.4755284), (-0.7694211, -0.58778524, -0.25000006), (-0.8090172, -0.58778524, 0), (-0.7694211, -0.58778524, 0.25000006), (-0.65450865, -0.58778524, 0.47552836), (-0.47552836, -0.58778524, 0.6545086), (-0.25000006, -0.58778524, 0.769421), (-2.4110586e-8, -0.58778524, 0.8090171), (0.24999999, -0.58778524, 0.769421), (0.47552827, -0.58778524, 0.65450853), (0.65450853, -0.58778524, 0.4755283), (0.7694209, -0.58778524, 0.25), (0.809017, -0.58778524, 0), (0.8473981, -0.45399052, -0.27533633), (0.7208399, -0.45399052, -0.5237208), (0.5237208, -0.45399052, -0.72083986), (0.2753363, -0.45399052, -0.847398), (0, -0.45399052, -0.89100695), (-0.2753363, -0.45399052, -0.847398), (-0.5237207, -0.45399052, -0.7208397), (-0.7208396, -0.45399052, -0.5237206), (-0.8473978, -0.45399052, -0.2753362), (-0.89100677, -0.45399052, 0), (-0.8473978, -0.45399052, 0.2753362), (-0.7208396, -0.45399052, 0.5237206), (-0.5237206, -0.45399052, 0.72083956), (-0.2753362, -0.45399052, 0.8473977), (-2.6554064e-8, -0.45399052, 0.89100665), (0.27533615, -0.45399052, 0.8473976), (0.5237205, -0.45399052, 0.7208395), (0.72083944, -0.45399052, 0.52372056), (0.84739757, -0.45399052, 0.27533618), (0.8910065, -0.45399052, 0), (0.9045091, -0.30901697, -0.2938928), (0.7694214, -0.30901697, -0.55901736), (0.55901736, -0.30901697, -0.76942134), (0.29389277, -0.30901697, -0.904509), (0, -0.30901697, -0.951057), (-0.29389277, -0.30901697, -0.90450895), (-0.55901724, -0.30901697, -0.7694212), (-0.76942116, -0.30901697, -0.5590172), (-0.90450877, -0.30901697, -0.2938927), (-0.9510568, -0.30901697, 0), (-0.90450877, -0.30901697, 0.2938927), (-0.7694211, -0.30901697, 0.5590171), (-0.5590171, -0.30901697, 0.76942104), (-0.2938927, -0.30901697, 0.90450865), (-2.8343694e-8, -0.30901697, 0.95105666), (0.29389262, -0.30901697, 0.9045086), (0.559017, -0.30901697, 0.769421), (0.7694209, -0.30901697, 0.55901706), (0.90450853, -0.30901697, 0.29389265), (0.95105654, -0.30901697, 0), (0.93934804, -0.15643437, -0.30521268), (0.7990572, -0.15643437, -0.580549), (0.580549, -0.15643437, -0.7990571), (0.30521265, -0.15643437, -0.9393479), (0, -0.15643437, -0.98768884), (-0.30521265, -0.15643437, -0.93934786), (-0.5805489, -0.15643437, -0.79905695), (-0.7990569, -0.15643437, -0.5805488), (-0.9393477, -0.15643437, -0.30521256), (-0.9876886, -0.15643437, 0), (-0.9393477, -0.15643437, 0.30521256), (-0.7990568, -0.15643437, 0.58054876), (-0.58054876, -0.15643437, 0.79905677), (-0.30521256, -0.15643437, 0.93934757), (-2.9435407e-8, -0.15643437, 0.9876885), (0.30521247, -0.15643437, 0.93934757), (0.58054864, -0.15643437, 0.7990567), (0.79905665, -0.15643437, 0.5805487), (0.9393475, -0.15643437, 0.3052125), (0.98768836, -0.15643437, 0), (0.95105714, 0, -0.30901718), (0.80901754, 0, -0.5877856), (0.5877856, 0, -0.8090175), (0.30901715, 0, -0.951057), (0, 0, -1.0000005), (-0.30901715, 0, -0.95105696), (-0.5877855, 0, -0.8090173), (-0.80901724, 0, -0.5877854), (-0.9510568, 0, -0.30901706), (-1.0000002, 0, 0), (-0.9510568, 0, 0.30901706), (-0.8090172, 0, 0.58778536), (-0.58778536, 0, 0.8090171), (-0.30901706, 0, 0.95105666), (-2.9802322e-8, 0, 1.0000001), (0.30901697, 0, 0.9510566), (0.58778524, 0, 0.80901706), (0.809017, 0, 0.5877853), (0.95105654, 0, 0.309017), (1, 0, 0), (0.93934804, 0.15643437, -0.30521268), (0.7990572, 0.15643437, -0.580549), (0.580549, 0.15643437, -0.7990571), (0.30521265, 0.15643437, -0.9393479), (0, 0.15643437, -0.98768884), (-0.30521265, 0.15643437, -0.93934786), (-0.5805489, 0.15643437, -0.79905695), (-0.7990569, 0.15643437, -0.5805488), (-0.9393477, 0.15643437, -0.30521256), (-0.9876886, 0.15643437, 0), (-0.9393477, 0.15643437, 0.30521256), (-0.7990568, 0.15643437, 0.58054876), (-0.58054876, 0.15643437, 0.79905677), (-0.30521256, 0.15643437, 0.93934757), (-2.9435407e-8, 0.15643437, 0.9876885), (0.30521247, 0.15643437, 0.93934757), (0.58054864, 0.15643437, 0.7990567), (0.79905665, 0.15643437, 0.5805487), (0.9393475, 0.15643437, 0.3052125), (0.98768836, 0.15643437, 0), (0.9045091, 0.30901697, -0.2938928), (0.7694214, 0.30901697, -0.55901736), (0.55901736, 0.30901697, -0.76942134), (0.29389277, 0.30901697, -0.904509), (0, 0.30901697, -0.951057), (-0.29389277, 0.30901697, -0.90450895), (-0.55901724, 0.30901697, -0.7694212), (-0.76942116, 0.30901697, -0.5590172), (-0.90450877, 0.30901697, -0.2938927), (-0.9510568, 0.30901697, 0), (-0.90450877, 0.30901697, 0.2938927), (-0.7694211, 0.30901697, 0.5590171), (-0.5590171, 0.30901697, 0.76942104), (-0.2938927, 0.30901697, 0.90450865), (-2.8343694e-8, 0.30901697, 0.95105666), (0.29389262, 0.30901697, 0.9045086), (0.559017, 0.30901697, 0.769421), (0.7694209, 0.30901697, 0.55901706), (0.90450853, 0.30901697, 0.29389265), (0.95105654, 0.30901697, 0), (0.8473981, 0.45399052, -0.27533633), (0.7208399, 0.45399052, -0.5237208), (0.5237208, 0.45399052, -0.72083986), (0.2753363, 0.45399052, -0.847398), (0, 0.45399052, -0.89100695), (-0.2753363, 0.45399052, -0.847398), (-0.5237207, 0.45399052, -0.7208397), (-0.7208396, 0.45399052, -0.5237206), (-0.8473978, 0.45399052, -0.2753362), (-0.89100677, 0.45399052, 0), (-0.8473978, 0.45399052, 0.2753362), (-0.7208396, 0.45399052, 0.5237206), (-0.5237206, 0.45399052, 0.72083956), (-0.2753362, 0.45399052, 0.8473977), (-2.6554064e-8, 0.45399052, 0.89100665), (0.27533615, 0.45399052, 0.8473976), (0.5237205, 0.45399052, 0.7208395), (0.72083944, 0.45399052, 0.52372056), (0.84739757, 0.45399052, 0.27533618), (0.8910065, 0.45399052, 0), (0.7694214, 0.58778524, -0.25000015), (0.65450895, 0.58778524, -0.47552854), (0.47552854, 0.58778524, -0.6545089), (0.25000012, 0.58778524, -0.7694213), (0, 0.58778524, -0.80901736), (-0.25000012, 0.58778524, -0.7694212), (-0.47552845, 0.58778524, -0.65450877), (-0.6545087, 0.58778524, -0.4755284), (-0.7694211, 0.58778524, -0.25000006), (-0.8090172, 0.58778524, 0), (-0.7694211, 0.58778524, 0.25000006), (-0.65450865, 0.58778524, 0.47552836), (-0.47552836, 0.58778524, 0.6545086), (-0.25000006, 0.58778524, 0.769421), (-2.4110586e-8, 0.58778524, 0.8090171), (0.24999999, 0.58778524, 0.769421), (0.47552827, 0.58778524, 0.65450853), (0.65450853, 0.58778524, 0.4755283), (0.7694209, 0.58778524, 0.25), (0.809017, 0.58778524, 0), (0.67249894, 0.70710677, -0.21850814), (0.5720618, 0.70710677, -0.41562718), (0.41562718, 0.70710677, -0.5720617), (0.21850812, 0.70710677, -0.6724989), (0, 0.70710677, -0.7071071), (-0.21850812, 0.70710677, -0.6724988), (-0.4156271, 0.70710677, -0.5720616), (-0.57206154, 0.70710677, -0.41562706), (-0.6724987, 0.70710677, -0.21850805), (-0.70710695, 0.70710677, 0), (-0.6724987, 0.70710677, 0.21850805), (-0.57206154, 0.70710677, 0.415627), (-0.415627, 0.70710677, 0.5720615), (-0.21850805, 0.70710677, 0.6724986), (-2.1073424e-8, 0.70710677, 0.7071068), (0.21850799, 0.70710677, 0.6724986), (0.4156269, 0.70710677, 0.5720614), (0.5720614, 0.70710677, 0.41562697), (0.6724985, 0.70710677, 0.21850802), (0.70710677, 0.70710677, 0), (0.55901736, 0.809017, -0.18163574), (0.47552857, 0.809017, -0.3454917), (0.3454917, 0.809017, -0.47552854), (0.18163572, 0.809017, -0.5590173), (0, 0.809017, -0.58778554), (-0.18163572, 0.809017, -0.55901724), (-0.34549165, 0.809017, -0.47552842), (-0.4755284, 0.809017, -0.3454916), (-0.5590171, 0.809017, -0.18163566), (-0.58778536, 0.809017, 0), (-0.5590171, 0.809017, 0.18163566), (-0.47552836, 0.809017, 0.34549156), (-0.34549156, 0.809017, 0.47552833), (-0.18163566, 0.809017, 0.55901706), (-1.7517365e-8, 0.809017, 0.5877853), (0.18163562, 0.809017, 0.55901706), (0.3454915, 0.809017, 0.4755283), (0.47552827, 0.809017, 0.34549153), (0.559017, 0.809017, 0.18163563), (0.58778524, 0.809017, 0), (0.43177092, 0.8910065, -0.14029087), (0.3672863, 0.8910065, -0.2668491), (0.2668491, 0.8910065, -0.36728626), (0.14029086, 0.8910065, -0.43177086), (0, 0.8910065, -0.45399073), (-0.14029086, 0.8910065, -0.43177083), (-0.26684904, 0.8910065, -0.36728618), (-0.36728615, 0.8910065, -0.266849), (-0.43177077, 0.8910065, -0.14029081), (-0.45399064, 0.8910065, 0), (-0.43177077, 0.8910065, 0.14029081), (-0.36728612, 0.8910065, 0.26684898), (-0.26684898, 0.8910065, 0.36728612), (-0.14029081, 0.8910065, 0.4317707), (-1.3529972e-8, 0.8910065, 0.45399058), (0.14029078, 0.8910065, 0.43177068), (0.26684892, 0.8910065, 0.3672861), (0.36728606, 0.8910065, 0.26684895), (0.43177065, 0.8910065, 0.1402908), (0.45399052, 0.8910065, 0), (0.29389283, 0.95105654, -0.095491566), (0.25000018, 0.95105654, -0.18163574), (0.18163574, 0.95105654, -0.25000015), (0.09549155, 0.95105654, -0.2938928), (0, 0.95105654, -0.30901715), (-0.09549155, 0.95105654, -0.29389277), (-0.18163571, 0.95105654, -0.2500001), (-0.2500001, 0.95105654, -0.1816357), (-0.2938927, 0.95105654, -0.09549153), (-0.30901706, 0.95105654, 0), (-0.2938927, 0.95105654, 0.09549153), (-0.25000006, 0.95105654, 0.18163568), (-0.18163568, 0.95105654, 0.25000006), (-0.09549153, 0.95105654, 0.29389268), (-9.209424e-9, 0.95105654, 0.30901703), (0.0954915, 0.95105654, 0.29389265), (0.18163563, 0.95105654, 0.25000003), (0.25, 0.95105654, 0.18163565), (0.29389265, 0.95105654, 0.095491506), (0.309017, 0.95105654, 0), (0.14877813, 0.98768836, -0.048340943), (0.12655823, 0.98768836, -0.09194993), (0.09194993, 0.98768836, -0.12655823), (0.048340935, 0.98768836, -0.14877811), (0, 0.98768836, -0.15643455), (-0.048340935, 0.98768836, -0.1487781), (-0.09194992, 0.98768836, -0.1265582), (-0.12655818, 0.98768836, -0.0919499), (-0.14877807, 0.98768836, -0.048340924), (-0.15643452, 0.98768836, 0), (-0.14877807, 0.98768836, 0.048340924), (-0.12655818, 0.98768836, 0.091949895), (-0.091949895, 0.98768836, 0.12655817), (-0.048340924, 0.98768836, 0.14877805), (-4.6621107e-9, 0.98768836, 0.15643449), (0.04834091, 0.98768836, 0.14877804), (0.09194988, 0.98768836, 0.12655815), (0.12655815, 0.98768836, 0.09194989), (0.14877804, 0.98768836, 0.048340913), (0.15643448, 0.98768836, 0), (0, -1, 0), (0, 1, 0)] + + def GeomSubset "SphereUpperHalf" + { + uniform token elementType = "face" + int[] indices = [180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399] + } +} +