/****************************************************************************** * Renders the geometry. ******************************************************************************/ void OpenGLArrowPrimitive::render(SceneRenderer* renderer) { OVITO_REPORT_OPENGL_ERRORS(); OVITO_ASSERT(_contextGroup == QOpenGLContextGroup::currentContextGroup()); OVITO_ASSERT(_elementCount >= 0); OVITO_ASSERT(_mappedChunkIndex == -1); ViewportSceneRenderer* vpRenderer = dynamic_object_cast<ViewportSceneRenderer>(renderer); if(_elementCount <= 0 || !vpRenderer) return; vpRenderer->rebindVAO(); if(shadingMode() == NormalShading) { if(renderingQuality() == HighQuality && shape() == CylinderShape) renderWithElementInfo(vpRenderer); else renderWithNormals(vpRenderer); } else if(shadingMode() == FlatShading) { renderWithElementInfo(vpRenderer); } OVITO_REPORT_OPENGL_ERRORS(); }
/****************************************************************************** * Renders the geometry as with extra information passed to the vertex shader. ******************************************************************************/ void OpenGLArrowPrimitive::renderWithElementInfo(ViewportSceneRenderer* renderer) { QOpenGLShaderProgram* shader = renderer->isPicking() ? _pickingShader : _shader; if(!shader) return; if(!shader->bind()) throw Exception(QStringLiteral("Failed to bind OpenGL shader.")); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); shader->setUniformValue("modelview_matrix", (QMatrix4x4)renderer->modelViewTM()); shader->setUniformValue("modelview_uniform_scale", (float)pow(std::abs(renderer->modelViewTM().determinant()), (FloatType(1.0/3.0)))); shader->setUniformValue("modelview_projection_matrix", (QMatrix4x4)(renderer->projParams().projectionMatrix * renderer->modelViewTM())); shader->setUniformValue("projection_matrix", (QMatrix4x4)renderer->projParams().projectionMatrix); shader->setUniformValue("inverse_projection_matrix", (QMatrix4x4)renderer->projParams().inverseProjectionMatrix); shader->setUniformValue("is_perspective", renderer->projParams().isPerspective); AffineTransformation viewModelTM = renderer->modelViewTM().inverse(); Vector3 eye_pos = viewModelTM.translation(); shader->setUniformValue("eye_pos", eye_pos.x(), eye_pos.y(), eye_pos.z()); Vector3 viewDir = viewModelTM * Vector3(0,0,1); shader->setUniformValue("parallel_view_dir", viewDir.x(), viewDir.y(), viewDir.z()); GLint viewportCoords[4]; glGetIntegerv(GL_VIEWPORT, viewportCoords); shader->setUniformValue("viewport_origin", (float)viewportCoords[0], (float)viewportCoords[1]); shader->setUniformValue("inverse_viewport_size", 2.0f / (float)viewportCoords[2], 2.0f / (float)viewportCoords[3]); GLint pickingBaseID; if(renderer->isPicking()) { pickingBaseID = renderer->registerSubObjectIDs(elementCount()); renderer->activateVertexIDs(shader, _chunkSize * _verticesPerElement, true); OVITO_CHECK_OPENGL(shader->setUniformValue("verticesPerElement", (GLint)_verticesPerElement)); } for(int chunkIndex = 0; chunkIndex < _verticesWithElementInfo.size(); chunkIndex++, pickingBaseID += _chunkSize) { int chunkStart = chunkIndex * _chunkSize; int chunkSize = std::min(_elementCount - chunkStart, _chunkSize); if(renderer->isPicking()) shader->setUniformValue("pickingBaseID", pickingBaseID); _verticesWithElementInfo[chunkIndex].bindPositions(renderer, shader, offsetof(VertexWithElementInfo, pos)); _verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_base", GL_FLOAT, offsetof(VertexWithElementInfo, base), 3, sizeof(VertexWithElementInfo)); _verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_axis", GL_FLOAT, offsetof(VertexWithElementInfo, dir), 3, sizeof(VertexWithElementInfo)); _verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_radius", GL_FLOAT, offsetof(VertexWithElementInfo, radius), 1, sizeof(VertexWithElementInfo)); if(!renderer->isPicking()) _verticesWithElementInfo[chunkIndex].bindColors(renderer, shader, 4, offsetof(VertexWithElementInfo, color)); if(_usingGeometryShader && (shadingMode() == FlatShading || renderingQuality() == HighQuality)) { OVITO_CHECK_OPENGL(glDrawArrays(GL_POINTS, 0, chunkSize)); } else { int stripPrimitivesPerElement = _stripPrimitiveVertexCounts.size() / _chunkSize; OVITO_CHECK_OPENGL(renderer->glMultiDrawArrays(GL_TRIANGLE_STRIP, _stripPrimitiveVertexStarts.data(), _stripPrimitiveVertexCounts.data(), stripPrimitivesPerElement * chunkSize)); int fanPrimitivesPerElement = _fanPrimitiveVertexCounts.size() / _chunkSize; OVITO_CHECK_OPENGL(renderer->glMultiDrawArrays(GL_TRIANGLE_FAN, _fanPrimitiveVertexStarts.data(), _fanPrimitiveVertexCounts.data(), fanPrimitivesPerElement * chunkSize)); } _verticesWithElementInfo[chunkIndex].detachPositions(renderer, shader); _verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_base"); _verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_axis"); _verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_radius"); if(!renderer->isPicking()) _verticesWithElementInfo[chunkIndex].detachColors(renderer, shader); } shader->enableAttributeArray("cylinder_base"); shader->enableAttributeArray("cylinder_axis"); shader->enableAttributeArray("cylinder_radius"); if(renderer->isPicking()) renderer->deactivateVertexIDs(shader, true); shader->release(); }
/****************************************************************************** * Creates the geometry for a single arrow element. ******************************************************************************/ void OpenGLArrowPrimitive::createArrowElement(int index, const Point3& pos, const Vector3& dir, const ColorA& color, FloatType width) { const float arrowHeadRadius = width * 2.5f; const float arrowHeadLength = arrowHeadRadius * 1.8f; if(shadingMode() == NormalShading) { // Build local coordinate system. Vector_3<float> t, u, v; float length = dir.length(); if(length != 0) { t = dir / length; if(dir.y() != 0 || dir.x() != 0) u = Vector_3<float>(dir.y(), -dir.x(), 0); else u = Vector_3<float>(-dir.z(), 0, dir.x()); u.normalize(); v = u.cross(t); } else { t.setZero(); u.setZero(); v.setZero(); } ColorAT<float> c = color; Point_3<float> v1 = pos; Point_3<float> v2; Point_3<float> v3 = v1 + dir; float r; if(length > arrowHeadLength) { v2 = v1 + t * (length - arrowHeadLength); r = arrowHeadRadius; } else { v2 = v1; r = arrowHeadRadius * length / arrowHeadLength; } OVITO_ASSERT(_mappedVerticesWithNormals); VertexWithNormal* vertex = _mappedVerticesWithNormals + (index * _verticesPerElement); // Generate vertices for cylinder. for(int i = 0; i <= _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * width; vertex->pos = v1 + d; vertex->normal = n; vertex->color = c; vertex++; vertex->pos = v2 + d; vertex->normal = n; vertex->color = c; vertex++; } // Generate vertices for head cone. for(int i = 0; i <= _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * r; vertex->pos = v2 + d; vertex->normal = n; vertex->color = c; vertex++; vertex->pos = v3; vertex->normal = n; vertex->color = c; vertex++; } // Generate vertices for cylinder cap. for(int i = 0; i < _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * width; vertex->pos = v1 + d; vertex->normal = Vector_3<float>(0,0,-1); vertex->color = c; vertex++; } // Generate vertices for cone cap. for(int i = 0; i < _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * r; vertex->pos = v2 + d; vertex->normal = Vector_3<float>(0,0,-1); vertex->color = c; vertex++; } } else if(shadingMode() == FlatShading) { Vector_3<float> t; float length = dir.length(); if(length != 0) t = dir / length; else t.setZero(); ColorAT<float> c = color; Point_3<float> base = pos; OVITO_ASSERT(_mappedVerticesWithElementInfo); VertexWithElementInfo* vertices = _mappedVerticesWithElementInfo + (index * _verticesPerElement); if(length > arrowHeadLength) { vertices[0].pos = Point_3<float>(length, 0, 0); vertices[1].pos = Point_3<float>(length - arrowHeadLength, arrowHeadRadius, 0); vertices[2].pos = Point_3<float>(length - arrowHeadLength, width, 0); vertices[3].pos = Point_3<float>(0, width, 0); vertices[4].pos = Point_3<float>(0, -width, 0); vertices[5].pos = Point_3<float>(length - arrowHeadLength, -width, 0); vertices[6].pos = Point_3<float>(length - arrowHeadLength, -arrowHeadRadius, 0); } else { float r = arrowHeadRadius * length / arrowHeadLength; vertices[0].pos = Point_3<float>(length, 0, 0); vertices[1].pos = Point_3<float>(0, r, 0); vertices[2].pos = Point_3<float>::Origin(); vertices[3].pos = Point_3<float>::Origin(); vertices[4].pos = Point_3<float>::Origin(); vertices[5].pos = Point_3<float>::Origin(); vertices[6].pos = Point_3<float>(0, -r, 0); } for(int i = 0; i < _verticesPerElement; i++, ++vertices) { vertices->base = base; vertices->dir = t; vertices->color = c; } } }
/****************************************************************************** * Allocates a particle buffer with the given number of elements. ******************************************************************************/ void OpenGLArrowPrimitive::startSetElements(int elementCount) { OVITO_ASSERT(elementCount >= 0); OVITO_ASSERT(QOpenGLContextGroup::currentContextGroup() == _contextGroup); OVITO_ASSERT(_mappedChunkIndex == -1); _verticesWithNormals.clear(); _verticesWithElementInfo.clear(); _elementCount = elementCount; bool renderMesh = true; int stripsPerElement; int fansPerElement; int verticesPerStrip; int verticesPerFan; if(shadingMode() == NormalShading) { verticesPerStrip = _cylinderSegments * 2 + 2; verticesPerFan = _cylinderSegments; if(shape() == ArrowShape) { stripsPerElement = 2; fansPerElement = 2; } else { stripsPerElement = 1; fansPerElement = 2; if(renderingQuality() == HighQuality) { if(_usingGeometryShader) { verticesPerStrip = 1; stripsPerElement = 1; } else { verticesPerStrip = 14; } fansPerElement = verticesPerFan = 0; renderMesh = false; } } } else if(shadingMode() == FlatShading) { fansPerElement = 1; stripsPerElement = 0; verticesPerStrip = 0; if(shape() == ArrowShape) verticesPerFan = 7; else verticesPerFan = 4; if(_usingGeometryShader && shape() == CylinderShape) { verticesPerFan = 1; } renderMesh = false; } else OVITO_ASSERT(false); // Determine the VBO chunk size. _verticesPerElement = stripsPerElement * verticesPerStrip + fansPerElement * verticesPerFan; int bytesPerVertex = renderMesh ? sizeof(VertexWithNormal) : sizeof(VertexWithElementInfo); _chunkSize = std::min(_maxVBOSize / _verticesPerElement / bytesPerVertex, _elementCount); // Allocate VBOs. for(int i = _elementCount; i > 0; i -= _chunkSize) { if(renderMesh) { OpenGLBuffer<VertexWithNormal> buffer; buffer.create(QOpenGLBuffer::StaticDraw, std::min(i, _chunkSize), _verticesPerElement); _verticesWithNormals.push_back(buffer); } else { OpenGLBuffer<VertexWithElementInfo> buffer; buffer.create(QOpenGLBuffer::StaticDraw, std::min(i, _chunkSize), _verticesPerElement); _verticesWithElementInfo.push_back(buffer); } } OVITO_REPORT_OPENGL_ERRORS(); // Prepare arrays to be passed to the glMultiDrawArrays() function. _stripPrimitiveVertexStarts.resize(_chunkSize * stripsPerElement); _stripPrimitiveVertexCounts.resize(_chunkSize * stripsPerElement); _fanPrimitiveVertexStarts.resize(_chunkSize * fansPerElement); _fanPrimitiveVertexCounts.resize(_chunkSize * fansPerElement); std::fill(_stripPrimitiveVertexCounts.begin(), _stripPrimitiveVertexCounts.end(), verticesPerStrip); std::fill(_fanPrimitiveVertexCounts.begin(), _fanPrimitiveVertexCounts.end(), verticesPerFan); auto ps_strip = _stripPrimitiveVertexStarts.begin(); auto ps_fan = _fanPrimitiveVertexStarts.begin(); for(GLint index = 0, baseIndex = 0; index < _chunkSize; index++) { for(int p = 0; p < stripsPerElement; p++, baseIndex += verticesPerStrip) *ps_strip++ = baseIndex; for(int p = 0; p < fansPerElement; p++, baseIndex += verticesPerFan) *ps_fan++ = baseIndex; } // Precompute cos() and sin() functions. if(shadingMode() == NormalShading) { _cosTable.resize(_cylinderSegments+1); _sinTable.resize(_cylinderSegments+1); for(int i = 0; i <= _cylinderSegments; i++) { float angle = (FLOATTYPE_PI * 2 / _cylinderSegments) * i; _cosTable[i] = std::cos(angle); _sinTable[i] = std::sin(angle); } } }
/****************************************************************************** * Creates the geometry for a single cylinder element. ******************************************************************************/ void OpenGLArrowPrimitive::createCylinderElement(int index, const Point3& pos, const Vector3& dir, const ColorA& color, FloatType width) { if(_usingGeometryShader && (shadingMode() == FlatShading || renderingQuality() == HighQuality)) { OVITO_ASSERT(_mappedVerticesWithElementInfo); OVITO_ASSERT(_verticesPerElement == 1); VertexWithElementInfo* vertex = _mappedVerticesWithElementInfo + index; vertex->pos = vertex->base = pos; vertex->dir = dir; vertex->color = color; vertex->radius = width; return; } if(shadingMode() == NormalShading) { // Build local coordinate system. Vector_3<float> t, u, v; float length = dir.length(); if(length != 0) { t = dir / length; if(dir.y() != 0 || dir.x() != 0) u = Vector_3<float>(dir.y(), -dir.x(), 0); else u = Vector_3<float>(-dir.z(), 0, dir.x()); u.normalize(); v = u.cross(t); } else { t.setZero(); u.setZero(); v.setZero(); } ColorAT<float> c = color; Point_3<float> v1 = pos; Point_3<float> v2 = v1 + dir; if(renderingQuality() != HighQuality) { OVITO_ASSERT(_mappedVerticesWithNormals); VertexWithNormal* vertex = _mappedVerticesWithNormals + (index * _verticesPerElement); // Generate vertices for cylinder mantle. for(int i = 0; i <= _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * width; vertex->pos = v1 + d; vertex->normal = n; vertex->color = c; vertex++; vertex->pos = v2 + d; vertex->normal = n; vertex->color = c; vertex++; } // Generate vertices for first cylinder cap. for(int i = 0; i < _cylinderSegments; i++) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * width; vertex->pos = v1 + d; vertex->normal = Vector_3<float>(0,0,-1); vertex->color = c; vertex++; } // Generate vertices for second cylinder cap. for(int i = _cylinderSegments - 1; i >= 0; i--) { Vector_3<float> n = _cosTable[i] * u + _sinTable[i] * v; Vector_3<float> d = n * width; vertex->pos = v2 + d; vertex->normal = Vector_3<float>(0,0,1); vertex->color = c; vertex++; } } else { // Create bounding box geometry around cylinder for raytracing. OVITO_ASSERT(_mappedVerticesWithElementInfo); VertexWithElementInfo* vertex = _mappedVerticesWithElementInfo + (index * _verticesPerElement); OVITO_ASSERT(_verticesPerElement == 14); u *= width; v *= width; Point3 corners[8] = { v1 - u - v, v1 - u + v, v1 + u - v, v1 + u + v, v2 - u - v, v2 - u + v, v2 + u + v, v2 + u - v }; const static size_t stripIndices[14] = { 3,2,6,7,4,2,0,3,1,6,5,4,1,0 }; for(int i = 0; i < 14; i++, vertex++) { vertex->pos = corners[stripIndices[i]]; vertex->base = v1; vertex->dir = dir; vertex->color = c; vertex->radius = width; } } } else if(shadingMode() == FlatShading) { Vector_3<float> t; float length = dir.length(); if(length != 0) t = dir / length; else t.setZero(); ColorAT<float> c = color; Point_3<float> base = pos; OVITO_ASSERT(_mappedVerticesWithElementInfo); VertexWithElementInfo* vertices = _mappedVerticesWithElementInfo + (index * _verticesPerElement); vertices[0].pos = Point_3<float>(0, width, 0); vertices[1].pos = Point_3<float>(0, -width, 0); vertices[2].pos = Point_3<float>(length, -width, 0); vertices[3].pos = Point_3<float>(length, width, 0); for(int i = 0; i < _verticesPerElement; i++, ++vertices) { vertices->base = base; vertices->dir = t; vertices->color = c; } } }
MStatus usdTranslatorExport::writer(const MFileObject &file, const MString &optionsString, MPxFileTranslator::FileAccessMode mode ) { std::string fileName(file.fullName().asChar()); JobExportArgs jobArgs; double startTime=1, endTime=1; bool append=false; // Get the options if ( optionsString.length() > 0 ) { MStringArray optionList; MStringArray theOption; optionsString.split(';', optionList); for(int i=0; i<(int)optionList.length(); ++i) { theOption.clear(); optionList[i].split('=', theOption); if (theOption[0] == MString("exportReferencesAsInstanceable")) { jobArgs.exportRefsAsInstanceable = theOption[1].asInt(); } if (theOption[0] == MString("shadingMode")) { // Set default (most common) options jobArgs.exportDisplayColor = true; jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->none; if (theOption[1]=="None") { jobArgs.exportDisplayColor = false; }else if (theOption[1]=="Look Colors") { jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->displayColor; } else if (theOption[1]=="RfM Shaders") { TfToken shadingMode("pxrRis"); if (PxrUsdMayaShadingModeRegistry::GetInstance().GetExporter(shadingMode)) { jobArgs.shadingMode = shadingMode; } } } if (theOption[0] == MString("exportUVs")) { jobArgs.exportMeshUVs = theOption[1].asInt(); jobArgs.exportNurbsExplicitUV = theOption[1].asInt(); } if (theOption[0] == MString("normalizeUVs")) { jobArgs.normalizeMeshUVs = theOption[1].asInt(); jobArgs.nurbsExplicitUVType = PxUsdExportJobArgsTokens->Uniform; } if (theOption[0] == MString("exportColorSets")) { jobArgs.exportColorSets = theOption[1].asInt(); } if (theOption[0] == MString("renderableOnly")) { jobArgs.excludeInvisible = theOption[1].asInt(); } if (theOption[0] == MString("allCameras")) { jobArgs.exportDefaultCameras = theOption[1].asInt(); } if (theOption[0] == MString("renderLayerMode")) { jobArgs.renderLayerMode = PxUsdExportJobArgsTokens->defaultLayer; if (theOption[1]=="Use Current Layer") { jobArgs.renderLayerMode = PxUsdExportJobArgsTokens->currentLayer; } else if (theOption[1]=="Modeling Variant Per Layer") { jobArgs.renderLayerMode = PxUsdExportJobArgsTokens->modelingVariant; } } if (theOption[0] == MString("mergeXForm")) { jobArgs.mergeTransformAndShape = theOption[1].asInt(); } if (theOption[0] == MString("defaultMeshScheme")) { if (theOption[1]=="Polygonal Mesh") { jobArgs.defaultMeshScheme = UsdGeomTokens->none; } else if (theOption[1]=="Bilinear SubDiv") { jobArgs.defaultMeshScheme = UsdGeomTokens->bilinear; } else if (theOption[1]=="CatmullClark SDiv") { jobArgs.defaultMeshScheme = UsdGeomTokens->catmullClark; } else if (theOption[1]=="Loop SDiv") { jobArgs.defaultMeshScheme = UsdGeomTokens->loop; } } if (theOption[0] == MString("exportVisibility")) { jobArgs.exportVisibility = theOption[1].asInt(); } if (theOption[0] == MString("animation")) { jobArgs.exportAnimation = theOption[1].asInt(); } if (theOption[0] == MString("startTime")) { startTime = theOption[1].asDouble(); } if (theOption[0] == MString("endTime")) { endTime = theOption[1].asDouble(); } } // Now resync start and end frame based on animation mode if (jobArgs.exportAnimation) { if (endTime<startTime) endTime=startTime; } else { startTime=MAnimControl::currentTime().value(); endTime=startTime; } } MSelectionList objSelList; if(mode == MPxFileTranslator::kExportActiveAccessMode) { // Get selected objects MGlobal::getActiveSelectionList(objSelList); } else if(mode == MPxFileTranslator::kExportAccessMode) { // Get all objects at DAG root objSelList.add("|*", true); } // Convert selection list to jobArgs dagPaths for (unsigned int i=0; i < objSelList.length(); i++) { MDagPath dagPath; if (objSelList.getDagPath(i, dagPath) == MS::kSuccess) { jobArgs.dagPaths.insert(dagPath); } } if (jobArgs.dagPaths.size()) { MTime oldCurTime = MAnimControl::currentTime(); usdWriteJob writeJob(jobArgs); if (writeJob.beginJob(fileName, append, startTime, endTime)) { for (double i=startTime;i<(endTime+1);i++) { MGlobal::viewFrame(i); writeJob.evalJob(i); } writeJob.endJob(); MGlobal::viewFrame(oldCurTime); } } else { MGlobal::displayWarning("No DAG nodes to export. Skipping"); } return MS::kSuccess; }
MStatus usdImport::doIt(const MArgList & args) { MStatus status; MArgDatabase argData(syntax(), args, &status); // Check that all flags were valid if (status != MS::kSuccess) { MGlobal::displayError("Invalid parameters detected. Exiting."); return status; } JobImportArgs jobArgs; //bool verbose = argData.isFlagSet("verbose"); std::string mFileName; if (argData.isFlagSet("file")) { // Get the value MString tmpVal; argData.getFlagArgument("file", 0, tmpVal); // resolve the path into an absolute path MFileObject absoluteFile; absoluteFile.setRawFullName(tmpVal); absoluteFile.setRawFullName( absoluteFile.resolvedFullName() ); // Make sure an absolute path if (!absoluteFile.exists()) { MGlobal::displayError("File does not exist. Exiting."); return MS::kFailure; } // Set the fileName mFileName = absoluteFile.resolvedFullName().asChar(); MGlobal::displayInfo(MString("Importing ") + MString(mFileName.c_str())); } if (mFileName.empty()) { MString error = "Non empty file specified. Skipping..."; MGlobal::displayError(error); return MS::kFailure; } if (argData.isFlagSet("shadingMode")) { MString stringVal; argData.getFlagArgument("shadingMode", 0, stringVal); TfToken shadingMode(stringVal.asChar()); if (shadingMode.IsEmpty()) { jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->displayColor; } else { if (PxrUsdMayaShadingModeRegistry::GetInstance().GetExporter(shadingMode)) { jobArgs.shadingMode = shadingMode; } else { MGlobal::displayError(TfStringPrintf("No shadingMode '%s' found. Setting shadingMode='none'", shadingMode.GetText()).c_str()); jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->none; } } } if (argData.isFlagSet("readAnimData")) { bool tmpBool = false; argData.getFlagArgument("readAnimData", 0, tmpBool); jobArgs.readAnimData = tmpBool; } // Specify usd PrimPath. Default will be "/<useFileBasename>" std::string mPrimPath; if (argData.isFlagSet("primPath")) { // Get the value MString tmpVal; argData.getFlagArgument("primPath", 0, tmpVal); mPrimPath = tmpVal.asChar(); } // Add variant (variantSet, variant). Multi-use std::map<std::string,std::string> mVariants; for (unsigned int i=0; i < argData.numberOfFlagUses("variant"); ++i) { MArgList tmpArgList; status = argData.getFlagArgumentList("variant", i, tmpArgList); // Get the value MString tmpKey = tmpArgList.asString(0, &status); MString tmpVal = tmpArgList.asString(1, &status); mVariants.insert( std::pair<std::string, std::string>(tmpKey.asChar(), tmpVal.asChar()) ); } if (argData.isFlagSet("assemblyRep")) { // Get the value MString stringVal; argData.getFlagArgument("assemblyRep", 0, stringVal); std::string assemblyRep = stringVal.asChar(); if (not assemblyRep.empty()) { jobArgs.assemblyRep = TfToken(assemblyRep); } } // Create the command if (mUsdReadJob) { delete mUsdReadJob; } // pass in assemblyTypeName and proxyShapeTypeName mUsdReadJob = new usdReadJob(mFileName, mPrimPath, mVariants, jobArgs, _assemblyTypeName, _proxyShapeTypeName); // Add optional command params if (argData.isFlagSet("parent")) { // Get the value MString tmpVal; argData.getFlagArgument("parent", 0, tmpVal); if (tmpVal.length()) { MSelectionList selList; selList.add(tmpVal); MDagPath dagPath; status = selList.getDagPath(0, dagPath); if (status != MS::kSuccess) { std::string errorStr = TfStringPrintf( "Invalid path \"%s\"for -parent.", tmpVal.asChar()); MGlobal::displayError(MString(errorStr.c_str())); return MS::kFailure; } mUsdReadJob->setMayaRootDagPath( dagPath ); } } // Execute the command std::vector<MDagPath> addedDagPaths; bool success = mUsdReadJob->doIt(&addedDagPaths); if (success) { TF_FOR_ALL(iter, addedDagPaths) { appendToResult(iter->fullPathName()); } }
/****************************************************************************** * Lets the display object render the data object. ******************************************************************************/ void ParticleDisplay::render(TimePoint time, DataObject* dataObject, const PipelineFlowState& flowState, SceneRenderer* renderer, ObjectNode* contextNode) { // Get input data. ParticlePropertyObject* positionProperty = dynamic_object_cast<ParticlePropertyObject>(dataObject); ParticlePropertyObject* radiusProperty = ParticlePropertyObject::findInState(flowState, ParticleProperty::RadiusProperty); ParticlePropertyObject* colorProperty = ParticlePropertyObject::findInState(flowState, ParticleProperty::ColorProperty); ParticleTypeProperty* typeProperty = dynamic_object_cast<ParticleTypeProperty>(ParticlePropertyObject::findInState(flowState, ParticleProperty::ParticleTypeProperty)); ParticlePropertyObject* selectionProperty = renderer->isInteractive() ? ParticlePropertyObject::findInState(flowState, ParticleProperty::SelectionProperty) : nullptr; ParticlePropertyObject* transparencyProperty = ParticlePropertyObject::findInState(flowState, ParticleProperty::TransparencyProperty); ParticlePropertyObject* shapeProperty = ParticlePropertyObject::findInState(flowState, ParticleProperty::AsphericalShapeProperty); if(shadingMode() != ParticlePrimitive::NormalShading) shapeProperty = nullptr; // Get number of particles. int particleCount = positionProperty ? (int)positionProperty->size() : 0; // Do we have to re-create the geometry buffer from scratch? bool recreateBuffer = !_particleBuffer || !_particleBuffer->isValid(renderer); // If rendering quality is set to automatic, pick quality level based on number of particles. ParticlePrimitive::RenderingQuality renderQuality = effectiveRenderingQuality(renderer, positionProperty); // Determine effective particle shape. ParticlePrimitive::ParticleShape effectiveParticleShape = particleShape(); if(effectiveParticleShape == ParticlePrimitive::SquareShape && shapeProperty != nullptr) effectiveParticleShape = ParticlePrimitive::BoxShape; else shapeProperty = nullptr; // Set shading mode and rendering quality. if(!recreateBuffer) { recreateBuffer |= !(_particleBuffer->setShadingMode(shadingMode())); recreateBuffer |= !(_particleBuffer->setRenderingQuality(renderQuality)); recreateBuffer |= !(_particleBuffer->setParticleShape(effectiveParticleShape)); recreateBuffer |= ((transparencyProperty != nullptr) != _particleBuffer->translucentParticles()); } // Do we have to resize the render buffer? bool resizeBuffer = recreateBuffer || (_particleBuffer->particleCount() != particleCount); // Do we have to update the particle positions in the render buffer? bool updatePositions = _positionsCacheHelper.updateState(positionProperty) || resizeBuffer; // Do we have to update the particle radii in the geometry buffer? bool updateRadii = _radiiCacheHelper.updateState( radiusProperty, typeProperty, defaultParticleRadius()) || resizeBuffer; // Do we have to update the particle colors in the geometry buffer? bool updateColors = _colorsCacheHelper.updateState( colorProperty, typeProperty, selectionProperty, transparencyProperty, positionProperty) || resizeBuffer; // Do we have to update the particle shapes in the geometry buffer? bool updateShapes = _shapesCacheHelper.updateState( shapeProperty) || resizeBuffer; // Re-create the geometry buffer if necessary. if(recreateBuffer) _particleBuffer = renderer->createParticlePrimitive(shadingMode(), renderQuality, effectiveParticleShape, transparencyProperty != nullptr); // Re-size the geometry buffer if necessary. if(resizeBuffer) _particleBuffer->setSize(particleCount); // Update position buffer. if(updatePositions && positionProperty) { OVITO_ASSERT(positionProperty->size() == particleCount); _particleBuffer->setParticlePositions(positionProperty->constDataPoint3()); } // Update radius buffer. if(updateRadii && particleCount) { if(radiusProperty) { // Take particle radii directly from the radius property. OVITO_ASSERT(radiusProperty->size() == particleCount); _particleBuffer->setParticleRadii(radiusProperty->constDataFloat()); } else if(typeProperty) { // Assign radii based on particle types. OVITO_ASSERT(typeProperty->size() == particleCount); // Build a lookup map for particle type raii. const std::map<int,FloatType> radiusMap = typeProperty->radiusMap(); // Skip the following loop if all per-type radii are zero. In this case, simply use the default radius for all particles. if(std::any_of(radiusMap.cbegin(), radiusMap.cend(), [](const std::pair<int,FloatType>& it) { return it.second != 0; })) { // Allocate memory buffer. std::vector<FloatType> particleRadii(particleCount, defaultParticleRadius()); // Fill radius array. const int* t = typeProperty->constDataInt(); for(auto c = particleRadii.begin(); c != particleRadii.end(); ++c, ++t) { auto it = radiusMap.find(*t); // Set particle radius only if the type's radius is non-zero. if(it != radiusMap.end() && it->second != 0) *c = it->second; } _particleBuffer->setParticleRadii(particleRadii.data()); } else { // Assign a constant radius to all particles. _particleBuffer->setParticleRadius(defaultParticleRadius()); } } else { // Assign a constant radius to all particles. _particleBuffer->setParticleRadius(defaultParticleRadius()); } } // Update color buffer. if(updateColors && particleCount) { if(colorProperty && !selectionProperty && !transparencyProperty) { // Direct particle colors. OVITO_ASSERT(colorProperty->size() == particleCount); _particleBuffer->setParticleColors(colorProperty->constDataColor()); } else { std::vector<Color> colors(particleCount); particleColors(colors, colorProperty, typeProperty, selectionProperty); if(!transparencyProperty) { _particleBuffer->setParticleColors(colors.data()); } else { // Add alpha channel based on transparency particle property. std::vector<ColorA> colorsWithAlpha(particleCount); const FloatType* t = transparencyProperty->constDataFloat(); auto c_in = colors.cbegin(); for(auto c_out = colorsWithAlpha.begin(); c_out != colorsWithAlpha.end(); ++c_out, ++c_in, ++t) { c_out->r() = c_in->r(); c_out->g() = c_in->g(); c_out->b() = c_in->b(); c_out->a() = FloatType(1) - (*t); } _particleBuffer->setParticleColors(colorsWithAlpha.data()); } } } // Update shapes buffer. if(updateShapes && particleCount) { if(shapeProperty) { OVITO_ASSERT(shapeProperty->size() == particleCount); _particleBuffer->setParticleShapes(shapeProperty->constDataVector3()); } } if(renderer->isPicking()) { OORef<ParticlePickInfo> pickInfo(new ParticlePickInfo(flowState)); renderer->beginPickObject(contextNode, pickInfo); } _particleBuffer->render(renderer); if(renderer->isPicking()) { renderer->endPickObject(); } }
void MainWindow::on_actionSMOOTH_triggered() { emit shadingMode(2); }
void MainWindow::on_actionFLAT_triggered() { emit shadingMode(1); }