void My_TestGLDrawing::OffscreenTest() { DrawScene(); WriteToFile("color", "color1_unselected.png"); // select cube0 _picker.Pick(GfVec2i(319,221), GfVec2i(320,222)); DrawScene(); WriteToFile("color", "color2_cube0_pickable.png"); HdSelectionSharedPtr selection = _picker.GetSelection(); HdSelection::HighlightMode mode = HdSelection::HighlightModeSelect; TF_VERIFY(selection->GetSelectedPrimPaths(mode).size() == 1); TF_VERIFY(selection->GetSelectedPrimPaths(mode)[0] == SdfPath("/cube0")); // make cube0 unpickable; it should not let us pick cube1 since it occludes SdfPathVector excludePaths = {SdfPath("/cube0")}; _pickablesCol.SetExcludePaths(excludePaths); _picker.SetDoUnpickablesOcclude(true); _picker.Pick(GfVec2i(319,221), GfVec2i(320,222)); DrawScene(); WriteToFile("color", "color3_cube0_unpickable.png"); selection = _picker.GetSelection(); //TF_VERIFY(selection->GetSelectedPrimPaths(mode).size() == 0); }
/* virtual */ void Hdx_UnitTestWindow::OnPaintGL() { // // Update the draw target's size and execute the unit test with // the draw target bound. // _drawTarget->Bind(); _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->DrawTest(); _drawTarget->Unbind(); // // Blit the resulting color buffer to the window (this is a noop // if we're drawing offscreen). // glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, _drawTarget->GetFramebufferId()); glBlitFramebuffer(0, 0, GetWidth(), GetHeight(), 0, 0, GetWidth(), GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); }
void Picker::Pick(GfVec2i const& startPos, GfVec2i const& endPos) { if (!_intersector) return; // for readability GfVec2i const& pickRadius = _pParams.pickRadius; float const& width = _pParams.screenWidth; float const& height = _pParams.screenHeight; GfFrustum const& frustum = _pParams.viewFrustum; GfMatrix4d const& viewMatrix = _pParams.viewMatrix; int fwidth = std::max(pickRadius[0], std::abs(startPos[0] - endPos[0])); int fheight = std::max(pickRadius[1], std::abs(startPos[1] - endPos[1])); _intersector->SetResolution(GfVec2i(fwidth, fheight)); GfVec2d min(2*startPos[0]/width-1, 1-2*startPos[1]/height); GfVec2d max(2*(endPos[0]+1)/width-1, 1-2*(endPos[1]+1)/height); // scale window GfVec2d origin = frustum.GetWindow().GetMin(); GfVec2d scale = frustum.GetWindow().GetMax() - frustum.GetWindow().GetMin(); min = origin + GfCompMult(scale, 0.5 * (GfVec2d(1.0, 1.0) + min)); max = origin + GfCompMult(scale, 0.5 * (GfVec2d(1.0, 1.0) + max)); GfFrustum pickFrustum(frustum); pickFrustum.SetWindow(GfRange2d(min, max)); HdxIntersector::Params iParams; iParams.pickTarget = _pParams.pickTarget; iParams.doUnpickablesOcclude = _pParams.doUnpickablesOcclude; iParams.hitMode = HdxIntersector::HitFirst; iParams.projectionMatrix = pickFrustum.ComputeProjectionMatrix(); iParams.viewMatrix = viewMatrix; std::cout << "Pick " << startPos << " - " << endPos << "\n"; HdxIntersector::Result result; _intersector->Query(iParams, *_pParams.pickablesCol, _pParams.engine, &result); HdxIntersector::HitSet hits; HdSelectionSharedPtr selection(new HdSelection); if (result.ResolveUnique(&hits)) { AggregatedHits aggrHits = _AggregateHits(hits); for(const auto& pair : aggrHits) { _ProcessHit(pair.second, _pParams.pickTarget, _pParams.highlightMode, selection); } } _selectionTracker->SetSelection(selection); }
void Hdx_UnitTestWindow::OffscreenTest() { _drawTarget->Bind(); _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->OffscreenTest(); _drawTarget->Unbind(); }
void My_TestGLDrawing::MouseRelease(int button, int x, int y, int modKeys) { Hdx_UnitTestGLDrawing::MouseRelease(button, x, y, modKeys); if (!(modKeys & GarchGLDebugWindow::Alt)) { _picker.Pick(_startPos, _endPos); } _startPos = _endPos = GfVec2i(0); }
GlfSimpleLightingContext::GlfSimpleLightingContext() : _shadows(new GlfSimpleShadowArray(GfVec2i(1024, 1024), 0)), _worldToViewMatrix(1.0), _projectionMatrix(1.0), _sceneAmbient(0.01, 0.01, 0.01, 1.0), _useLighting(false), _useShadows(false), _useColorMaterialDiffuse(false), _lightingUniformBlockValid(false), _shadowUniformBlockValid(false), _materialUniformBlockValid(false) { }
void My_TestGLDrawing::_SetPickParams() { HdxUnitTestUtils::PickParams pParams; pParams.pickRadius = GfVec2i(4,4); pParams.screenWidth = GetWidth(); pParams.screenHeight = GetHeight(); pParams.viewFrustum = GetFrustum(); pParams.viewMatrix = GetViewMatrix(); pParams.engine = &_engine; pParams.pickablesCol = &_pickablesCol; pParams.highlightMode = HdSelection::HighlightModeSelect; // unpickable occlusion is false by default. _picker.SetPickParams(pParams); }
/* virtual */ void Hdx_UnitTestWindow::OnInitializeGL() { GlfGlewInit(); GlfRegisterDefaultDebugOutputMessageCallback(); GlfContextCaps::InitInstance(); std::cout << glGetString(GL_VENDOR) << "\n"; std::cout << glGetString(GL_RENDERER) << "\n"; std::cout << glGetString(GL_VERSION) << "\n"; // // Create an offscreen draw target which is the same size as this // widget and initialize the unit test with the draw target bound. // _drawTarget = GlfDrawTarget::New(GfVec2i(GetWidth(), GetHeight())); _drawTarget->Bind(); _drawTarget->AddAttachment("color", GL_RGBA, GL_FLOAT, GL_RGBA); _drawTarget->AddAttachment("depth", GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8); _unitTest->InitTest(); _drawTarget->Unbind(); }
bool HdxColorCorrectionTask::_CreateFramebufferResources(GLuint *texture) { // If framebufferSize is not provided we use the viewport size. // This can be incorrect if the client/app has changed the viewport to // be different then the render window size. (E.g. UsdView CameraMask mode) GfVec2i fboSize = _framebufferSize; if (fboSize[0] <= 0 || fboSize[1] <= 0) { GLint res[4] = {0}; glGetIntegerv(GL_VIEWPORT, res); fboSize = GfVec2i(res[2], res[3]); } bool createTexture = (_texture == 0 || fboSize != _textureSize); if (createTexture) { if (_texture != 0) { glDeleteTextures(1, &_texture); _texture = 0; } _textureSize = fboSize; GLint restoreTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &restoreTexture); glGenTextures(1, texture); glBindTexture(GL_TEXTURE_2D, *texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // XXX For step 1 we copy the client FBO texture, apply gamma to the // copy and write it back to the client texture. // A future step will likely create a 16F texture at the start of // hydra rendering and use color-correction to render the results back // into the client FBO texture. // XXX For now we assume we always want R16F. We could perhaps expose // this as client-API in HdxColorCorrectionTaskParams. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _textureSize[0], _textureSize[1], 0, GL_RGBA, GL_FLOAT, 0); glBindTexture(GL_TEXTURE_2D, restoreTexture); } bool switchedGLContext = !_owningContext || !_owningContext->IsCurrent(); if (switchedGLContext) { // If we're rendering with a different context than the render pass // was created with, recreate the FBO because FB is not shared. // XXX we need this since we use a FBO in _CopyTexture(). Ideally we // use HdxCompositor to do the copy, but for that we need to know the // textureId currently bound to the default framebuffer. However // glGetFramebufferAttachmentParameteriv will return and error when // trying to query the texture name bound to GL_BACK_LEFT. if (_owningContext && _owningContext->IsValid()) { GlfGLContextScopeHolder contextHolder(_owningContext); glDeleteFramebuffers(1, &_framebuffer); } _owningContext = GlfGLContext::GetCurrentGLContext(); if (!TF_VERIFY(_owningContext, "No valid GL context")) { return false; } if (_framebuffer == 0) { glGenFramebuffers(1, &_framebuffer); } } if (createTexture || switchedGLContext) { GLint restoreReadFB, restoreDrawFB; glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &restoreReadFB); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &restoreDrawFB); glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, restoreReadFB); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, restoreDrawFB); } GLF_POST_PENDING_GL_ERRORS(); return true; }
bool HdxIntersector::Query(HdxIntersector::Params const& params, HdRprimCollection const& col, HdEngine* engine, HdxIntersector::Result* result) { TRACE_FUNCTION(); // Make sure we're in a sane GL state before attempting anything. if (GlfHasLegacyGraphics()) { TF_RUNTIME_ERROR("framebuffer object not supported"); return false; } GlfGLContextSharedPtr context = GlfGLContext::GetCurrentGLContext(); if (!TF_VERIFY(context)) { TF_RUNTIME_ERROR("Invalid GL context"); return false; } if (!_drawTarget) { // Initialize the shared draw target late to ensure there is a valid GL // context, which may not be the case at constructon time. _Init(GfVec2i(128,128)); } GfVec2i size(_drawTarget->GetSize()); GfVec4i viewport(0, 0, size[0], size[1]); if (!TF_VERIFY(_renderPass)) { return false; } _renderPass->SetRprimCollection(col); // Setup state based on incoming params. _renderPassState->SetAlphaThreshold(params.alphaThreshold); _renderPassState->SetClipPlanes(params.clipPlanes); _renderPassState->SetCullStyle(params.cullStyle); _renderPassState->SetCamera(params.viewMatrix, params.projectionMatrix, viewport); _renderPassState->SetLightingEnabled(false); // Use a separate drawTarget (framebuffer object) for each GL context // that uses this renderer, but the drawTargets share attachments/textures. GlfDrawTargetRefPtr drawTarget = GlfDrawTarget::New(size); // Clone attachments into this context. Note that this will do a // light-weight copy of the textures, it does not produce a full copy of the // underlying images. drawTarget->Bind(); drawTarget->CloneAttachments(_drawTarget); // // Setup GL raster state // GLenum drawBuffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, drawBuffers); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); glClearColor(0,0,0,0); glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); GLF_POST_PENDING_GL_ERRORS(); // // Execute the picking pass // { GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Setup stencil state and prevent writes to color buffer. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, // stencil failed GL_KEEP, // stencil passed, depth failed GL_REPLACE); // stencil passed, depth passed // // Condition the stencil buffer. // params.depthMaskCallback(); // we expect any GL state changes are restored. // Disable stencil updates and setup the stencil test. glStencilFunc(GL_LESS, 0, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Clear depth incase the depthMaskCallback pollutes the depth buffer. glClear(GL_DEPTH_BUFFER_BIT); // Restore color outputs & setup state for rendering glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glFrontFace(GL_CCW); // // Enable conservative rasterization, if available. // // XXX: This wont work until it's in the Glew build. bool convRstr = glewIsSupported("GL_NV_conservative_raster"); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glEnable(GL_CONSERVATIVE_RASTERIZATION_NV); } // // Execute // // XXX: make intersector a Task HdTaskSharedPtrVector tasks; tasks.push_back(boost::make_shared<HdxIntersector_DrawTask>(_renderPass, _renderPassState, params.renderTags)); engine->Execute(*_index, tasks); glDisable(GL_STENCIL_TEST); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glDisable(GL_CONSERVATIVE_RASTERIZATION_NV); } // Restore glBindVertexArray(0); glDeleteVertexArrays(1, &vao); } GLF_POST_PENDING_GL_ERRORS(); // // Capture the result buffers to be resolved later. // size_t len = size[0] * size[1]; std::unique_ptr<unsigned char[]> primId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> instanceId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> elementId(new unsigned char[len*4]); std::unique_ptr<float[]> depths(new float[len]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("primId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &primId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("instanceId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &instanceId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("elementId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &elementId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("depth")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &depths[0]); glBindTexture(GL_TEXTURE_2D, 0); GLF_POST_PENDING_GL_ERRORS(); if (result) { *result = HdxIntersector::Result( std::move(primId), std::move(instanceId), std::move(elementId), std::move(depths), _index, params, viewport); } drawTarget->Unbind(); GLF_POST_PENDING_GL_ERRORS(); return true; }
const HdxIntersector::Hit * UsdMayaGLBatchRenderer::_GetHitInfo( M3dView& view, unsigned int pickResolution, bool singleSelection, const SdfPath& sharedId, const GfMatrix4d &localToWorldSpace) { // Guard against user clicking in viewer before renderer is setup if( !_renderIndex ) return NULL; // Selection only occurs once per display refresh, with all usd objects // simulataneously. If the selectQueue is not empty, that means that // a refresh has occurred, and we need to perform a new selection operation. if( !_selectQueue.empty() ) { TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "____________ SELECTION STAGE START ______________ (singleSelect = %d)\n", singleSelection ); GfMatrix4d viewMatrix; GfMatrix4d projectionMatrix; px_LegacyViewportUtils::GetViewSelectionMatrices(view, &viewMatrix, &projectionMatrix); // As Maya doesn't support batched selection, intersection testing is // actually performed in the first selection query that happens after a // render. This query occurs in the local space of SOME object, but // we need results in world space so that we have results for every // node available. worldToLocalSpace removes the local space we // happen to be in for the initial query. GfMatrix4d worldToLocalSpace(localToWorldSpace.GetInverse()); _intersector->SetResolution(GfVec2i(pickResolution, pickResolution)); HdxIntersector::Params qparams; qparams.viewMatrix = worldToLocalSpace * viewMatrix; qparams.projectionMatrix = projectionMatrix; qparams.alphaThreshold = 0.1; _selectResults.clear(); for( const auto &renderSetIter : _selectQueue ) { const RenderParams &renderParams = renderSetIter.second.first; const _SdfPathSet &renderPaths = renderSetIter.second.second; SdfPathVector roots(renderPaths.begin(), renderPaths.end()); TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "--- pickQueue, batch %zx, size %zu\n", renderSetIter.first, renderPaths.size()); TfToken colName = renderParams.geometryCol; HdRprimCollection rprims(colName, renderParams.drawRepr); rprims.SetRootPaths(roots); rprims.SetRenderTags(renderParams.renderTags); qparams.cullStyle = renderParams.cullStyle; qparams.renderTags = renderParams.renderTags; HdxIntersector::Result result; HdxIntersector::HitVector hits; glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_TEXTURE_BIT | GL_POLYGON_BIT); bool r = _intersector->Query(qparams, rprims, &_hdEngine, &result); glPopAttrib(); if( !r ) { continue; } if( singleSelection ) { hits.resize(1); if( !result.ResolveNearest(&hits.front()) ) continue; } else if( !result.ResolveAll(&hits) ) { continue; } for (const HdxIntersector::Hit& hit : hits) { auto itIfExists = _selectResults.insert( std::pair<SdfPath, HdxIntersector::Hit>(hit.delegateId, hit)); const bool &inserted = itIfExists.second; if( inserted ) continue; HdxIntersector::Hit& existingHit = itIfExists.first->second; if( hit.ndcDepth < existingHit.ndcDepth ) existingHit = hit; } } if( singleSelection && _selectResults.size()>1 ) { TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "!!! multiple singleSel hits found: %zu\n", _selectResults.size()); auto minIt=_selectResults.begin(); for( auto curIt=minIt; curIt!=_selectResults.end(); curIt++ ) { const HdxIntersector::Hit& curHit = curIt->second; const HdxIntersector::Hit& minHit = minIt->second; if( curHit.ndcDepth < minHit.ndcDepth ) minIt = curIt; } if( minIt!=_selectResults.begin() ) _selectResults.erase(_selectResults.begin(),minIt); minIt++; if( minIt!=_selectResults.end() ) _selectResults.erase(minIt,_selectResults.end()); } if( TfDebug::IsEnabled(PXRUSDMAYAGL_QUEUE_INFO) ) { for ( const auto &selectPair : _selectResults) { const SdfPath& path = selectPair.first; const HdxIntersector::Hit& hit = selectPair.second; cout << "NEW HIT: " << path << endl; cout << "\tdelegateId: " << hit.delegateId << endl; cout << "\tobjectId: " << hit.objectId << endl; cout << "\tndcDepth: " << hit.ndcDepth << endl; } } // As we've cached the results in pickBatches, we // can clear out the selection queue. _selectQueue.clear(); // Selection can happen after a refresh but before a draw call, so // clear out the render queue as well _renderQueue.clear(); // If nothing was selected, the view does not refresh, but this // means _selectQueue will not get processed again even if the // user attempts another selection. We fix the renderer state by // scheduling another refresh when the view is next idle. if( _selectResults.empty() ) view.scheduleRefresh(); TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "^^^^^^^^^^^^ SELECTION STAGE FINISH ^^^^^^^^^^^^^\n"); } return TfMapLookupPtr( _selectResults, sharedId ); }
bool PxrUsdMayaWriteUtil::SetUsdAttr( const MPlug& attrPlug, const UsdAttribute& usdAttr, const UsdTimeCode& usdTime, const bool translateMayaDoubleToUsdSinglePrecision) { if (!usdAttr || attrPlug.isNull()) { return false; } bool isAnimated = attrPlug.isDestination(); if (usdTime.IsDefault() == isAnimated) { return true; } // We perform a similar set of type-infererence acrobatics here as we do up // above in GetUsdTypeName(). See the comments there for more detail on a // few type-related oddities. MObject attrObj(attrPlug.attribute()); if (attrObj.hasFn(MFn::kEnumAttribute)) { MFnEnumAttribute enumAttrFn(attrObj); const short enumIndex = attrPlug.asShort(); const TfToken enumToken(enumAttrFn.fieldName(enumIndex).asChar()); return usdAttr.Set(enumToken, usdTime); } MFnNumericData::Type numericDataType; MFnData::Type typedDataType; MFnUnitAttribute::Type unitDataType; _GetMayaAttributeNumericTypedAndUnitDataTypes(attrPlug, numericDataType, typedDataType, unitDataType); if (attrObj.hasFn(MFn::kMatrixAttribute)) { typedDataType = MFnData::kMatrix; } switch (typedDataType) { case MFnData::kString: { MFnStringData stringDataFn(attrPlug.asMObject()); const std::string usdVal(stringDataFn.string().asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kMatrix: { MFnMatrixData matrixDataFn(attrPlug.asMObject()); const GfMatrix4d usdVal(matrixDataFn.matrix().matrix); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kStringArray: { MFnStringArrayData stringArrayDataFn(attrPlug.asMObject()); VtStringArray usdVal(stringArrayDataFn.length()); for (unsigned int i = 0; i < stringArrayDataFn.length(); ++i) { usdVal[i] = std::string(stringArrayDataFn[i].asChar()); } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kDoubleArray: { MFnDoubleArrayData doubleArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtFloatArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = (float)doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } else { VtDoubleArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kFloatArray: { MFnFloatArrayData floatArrayDataFn(attrPlug.asMObject()); VtFloatArray usdVal(floatArrayDataFn.length()); for (unsigned int i = 0; i < floatArrayDataFn.length(); ++i) { usdVal[i] = floatArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kIntArray: { MFnIntArrayData intArrayDataFn(attrPlug.asMObject()); VtIntArray usdVal(intArrayDataFn.length()); for (unsigned int i = 0; i < intArrayDataFn.length(); ++i) { usdVal[i] = intArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kPointArray: { MFnPointArrayData pointArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kVectorArray: { MFnVectorArrayData vectorArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } default: break; } switch (numericDataType) { case MFnNumericData::kBoolean: { const bool usdVal(attrPlug.asBool()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kByte: case MFnNumericData::kChar: { const int usdVal(attrPlug.asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kShort: { const int usdVal(attrPlug.asShort()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kInt: { const int usdVal(attrPlug.asInt()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Short: { short tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k2Int: { int tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Short: { short tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k3Int: { int tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kFloat: { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Float: { float tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2f(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Float: { float tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return _SetVec(usdAttr, GfVec3f(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kDouble: { const double usdVal(attrPlug.asDouble()); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set((float)usdVal, usdTime); } else { return usdAttr.Set(usdVal, usdTime); } break; } case MFnNumericData::k2Double: { double tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set(GfVec2f((float)tmp1, (float)tmp2), usdTime); } else { return usdAttr.Set(GfVec2d(tmp1, tmp2), usdTime); } break; } case MFnNumericData::k3Double: { double tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec3f((float)tmp1, (float)tmp2, (float)tmp3), usdTime); } else { return _SetVec(usdAttr, GfVec3d(tmp1, tmp2, tmp3), usdTime); } break; } case MFnNumericData::k4Double: { double tmp1, tmp2, tmp3, tmp4; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3, tmp4); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec4f((float)tmp1, (float)tmp2, (float)tmp3, (float)tmp4), usdTime); } else { return _SetVec(usdAttr, GfVec4d(tmp1, tmp2, tmp3, tmp4), usdTime); } break; } default: break; } switch (unitDataType) { case MFnUnitAttribute::kAngle: case MFnUnitAttribute::kDistance: if (translateMayaDoubleToUsdSinglePrecision) { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); } else { const double usdVal(attrPlug.asDouble()); return usdAttr.Set(usdVal, usdTime); } break; default: break; } return false; }
int main(int argc, char *argv[]) { // GfVec2f { float vals[] = { 1.0f, 2.0f }; GfVec2f v(vals); TF_AXIOM(v == GfVec2f(1,2)); float const *f = v.GetArray(); TF_AXIOM(f[0] == 1 and f[1] == 2); } // GfVec2i { int vals[] = { 1, 2 }; GfVec2i v(vals); TF_AXIOM(v == GfVec2i(1,2)); int const *i = v.GetArray(); TF_AXIOM(i[0] == 1 and i[1] == 2); v.Set(0, 1); TF_AXIOM(v == GfVec2i(0,1)); } // GfVec3i { int vals[] = { 1, 2, 3 }; GfVec3i v(vals); TF_AXIOM(v == GfVec3i(1,2,3)); int const *i = v.GetArray(); TF_AXIOM(i[0] == 1 and i[1] == 2 and i[2] == 3); v.Set(0, 1, 2); TF_AXIOM(v == GfVec3i(0,1,2)); } // GfVec4i { int vals[] = { 1, 2, 3, 4 }; GfVec4i v(vals); TF_AXIOM(v == GfVec4i(1,2,3,4)); int const *i = v.GetArray(); TF_AXIOM(i[0] == 1 and i[1] == 2 and i[2] == 3 and i[3] == 4); v.Set(0, 1, 2, 3); TF_AXIOM(v == GfVec4i(0,1,2,3)); } // GfVec3f { float vals[] = { 1.0f, 2.0f, 3.0f }; GfVec3f v(vals); TF_AXIOM(v == GfVec3f(1,2,3)); float const *f = v.GetArray(); TF_AXIOM(f[0] == 1 and f[1] == 2 and f[2] == 3); } // GfVec4f { float vals[] = { 1.0f, 2.0f, 3.0f, 4.0f }; GfVec4f v(vals); TF_AXIOM(v == GfVec4f(1,2,3,4)); float const *f = v.GetArray(); TF_AXIOM(f[0] == 1 and f[1] == 2 and f[2] == 3 and f[3] == 4); } // GfSize2, GfSize3 { size_t vals[] = {1, 2, 3}; TF_AXIOM(GfSize2(vals) == GfSize2(1,2)); TF_AXIOM(GfSize3(vals) == GfSize3(1,2,3)); } // GfMatrix2d { double vals[2][2] = {{1, 0}, {0, 1}}; TF_AXIOM(GfMatrix2d(vals) == GfMatrix2d(1)); GfMatrix2d m(vals); double const *d = m.GetArray(); TF_AXIOM(d[0] == 1 and d[1] == 0 and d[2] == 0 and d[3] == 1); } // GfMatrix2f { float vals[2][2] = {{1, 0}, {0, 1}}; TF_AXIOM(GfMatrix2f(vals) == GfMatrix2f(1)); GfMatrix2f m(vals); float const *f = m.GetArray(); TF_AXIOM(f[0] == 1 and f[1] == 0 and f[2] == 0 and f[3] == 1); } // GfMatrix3d { double vals[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; TF_AXIOM(GfMatrix3d(vals) == GfMatrix3d(1)); GfMatrix3d m(vals); double const *d = m.GetArray(); TF_AXIOM(d[0] == 1 and d[1] == 0 and d[2] == 0 and d[3] == 0 and d[4] == 1 and d[5] == 0 and d[6] == 0 and d[7] == 0 and d[8] == 1); } // GfMatrix4d { double vals[4][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; TF_AXIOM(GfMatrix4d(vals) == GfMatrix4d(1)); GfMatrix4d m(vals); double const *d = m.GetArray(); TF_AXIOM(d[ 0] == 1 and d[ 1] == 0 and d[ 2] == 0 and d[ 3] == 0 and d[ 4] == 0 and d[ 5] == 1 and d[ 6] == 0 and d[ 7] == 0 and d[ 8] == 0 and d[ 9] == 0 and d[10] == 1 and d[11] == 0 and d[12] == 0 and d[13] == 0 and d[14] == 0 and d[15] == 1); } // half { float halfPosInf = half::posInf(); TF_AXIOM(not std::isfinite(halfPosInf)); TF_AXIOM(std::isinf(halfPosInf)); float halfNegInf = half::negInf(); TF_AXIOM(not std::isfinite(halfNegInf)); TF_AXIOM(std::isinf(halfNegInf)); float halfqNan = half::qNan(); TF_AXIOM(std::isnan(halfqNan)); float halfsNan = half::sNan(); TF_AXIOM(std::isnan(halfsNan)); } return 0; }
SdfPath My_TestGLDrawing::PickScene(int pickX, int pickY, int * outInstanceIndex, int * outElementIndex) { int width = 128; int height = 128; GlfDrawTargetRefPtr drawTarget = GlfDrawTarget::New(GfVec2i(width, height)); drawTarget->Bind(); drawTarget->AddAttachment( "primId", GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8); drawTarget->AddAttachment( "instanceId", GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8); drawTarget->AddAttachment( "elementId", GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8); drawTarget->AddAttachment( "depth", GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F); drawTarget->Unbind(); drawTarget->Bind(); GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, drawBuffers); glEnable(GL_DEPTH_TEST); GLfloat clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; glClearBufferfv(GL_COLOR, 0, clearColor); glClearBufferfv(GL_COLOR, 1, clearColor); GLfloat clearDepth[1] = { 1.0f }; glClearBufferfv(GL_DEPTH, 0, clearDepth); PickParam pickParam; pickParam.location = GfVec2d(pickX, pickY); pickParam.viewport = GfVec4d(0, 0, width, height); DrawScene(&pickParam); drawTarget->Unbind(); GLubyte primId[width*height*4]; glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("primId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, primId); GLubyte instanceId[width*height*4]; glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("instanceId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, instanceId); GLubyte elementId[width*height*4]; glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("elementId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, elementId); GLfloat depths[width*height]; glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("depth")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, depths); double zMin = 1.0; int zMinIndex = -1; for (int y=0, i=0; y<height; y++) { for (int x=0; x<width; x++, i++) { if (depths[i] < zMin) { zMin = depths[i]; zMinIndex = i; } } } bool didHit = (zMin < 1.0); SdfPath result; if (didHit) { int idIndex = zMinIndex*4; result = _delegate->GetRenderIndex().GetRprimPathFromPrimId( HdxRenderSetupTask::DecodeIDRenderColor(&primId[idIndex])); if (outInstanceIndex) { *outInstanceIndex = HdxRenderSetupTask::DecodeIDRenderColor( &instanceId[idIndex]); } if (outElementIndex) { *outElementIndex = HdxRenderSetupTask::DecodeIDRenderColor( &elementId[idIndex]); } } return result; }
bool PxrUsdMayaWriteUtil::SetUsdAttr( const MPlug &plg, const UsdAttribute& usdAttr, const UsdTimeCode &usdTime) { MStatus status; if (!usdAttr || plg.isNull() ) { return false; } bool isAnimated = plg.isDestination(); if (usdTime.IsDefault() == isAnimated ) { return true; } // Set UsdAttr MObject attrObj = plg.attribute(); if (attrObj.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute attrNumericFn(attrObj); switch (attrNumericFn.unitType()) { case MFnNumericData::kBoolean: usdAttr.Set(plg.asBool(), usdTime); break; case MFnNumericData::kByte: case MFnNumericData::kChar: usdAttr.Set((int)plg.asChar(), usdTime); break; case MFnNumericData::kShort: usdAttr.Set(int(plg.asShort()), usdTime); break; case MFnNumericData::kInt: usdAttr.Set(int(plg.asInt()), usdTime); break; //case MFnNumericData::kLong: //case MFnNumericData::kAddr: // usdAttr.Set(plg.asInt(), usdTime); // break; case MFnNumericData::kFloat: usdAttr.Set(plg.asFloat(), usdTime); break; case MFnNumericData::kDouble: usdAttr.Set(plg.asDouble(), usdTime); break; case MFnNumericData::k2Short: { short tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k2Int: { int tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } //case MFnNumericData::k2Long: case MFnNumericData::k3Short: { short tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k3Int: { int tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } //case MFnNumericData::k3Long: case MFnNumericData::k2Float: { float tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2f(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Float: { float tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); _SetVec(usdAttr, GfVec3f(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k2Double: { double tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2d(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Double: { double tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); _SetVec(usdAttr, GfVec3d(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k4Double: { double tmp1, tmp2, tmp3, tmp4; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3, tmp4); _SetVec(usdAttr, GfVec4d(tmp1, tmp2, tmp3, tmp4), usdTime); break; } default: return false; } } else if (attrObj.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute attrTypedFn(attrObj); switch (attrTypedFn.attrType()) { case MFnData::kString: usdAttr.Set(std::string(plg.asString().asChar()), usdTime); break; case MFnData::kMatrix: { MFnMatrixData attrMatrixDataFn(plg.asMObject()); MMatrix mat1 = attrMatrixDataFn.matrix(); usdAttr.Set(GfMatrix4d(mat1.matrix), usdTime); break; } case MFnData::kStringArray: { MFnStringArrayData attrDataFn(plg.asMObject()); VtArray<std::string> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = std::string(attrDataFn[i].asChar()); } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kIntArray: { MFnIntArrayData attrDataFn(plg.asMObject()); VtArray<int> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kFloatArray: { MFnFloatArrayData attrDataFn(plg.asMObject()); VtArray<float> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kDoubleArray: { MFnDoubleArrayData attrDataFn(plg.asMObject()); VtArray<double> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kVectorArray: { MFnVectorArrayData attrDataFn(plg.asMObject()); VtArray<GfVec3d> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { MVector tmpMayaVal = attrDataFn[i]; usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kPointArray: { MFnPointArrayData attrDataFn(plg.asMObject()); VtArray<GfVec4d> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { MPoint tmpMayaVal = attrDataFn[i]; usdVal[i] = GfVec4d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2], tmpMayaVal[3]); } usdAttr.Set(usdVal, usdTime); break; } default: return false; } } else if (attrObj.hasFn(MFn::kUnitAttribute)) { //MFnUnitAttribute attrUnitFn(attrObj); return false; } else if (attrObj.hasFn(MFn::kEnumAttribute)) { MFnEnumAttribute attrEnumFn(attrObj); short enumIndex = plg.asShort(); TfToken enumToken( std::string(attrEnumFn.fieldName(enumIndex, &status).asChar()) ); usdAttr.Set(enumToken, usdTime); return false; } return true; }