def populateGeometry(self, requirements, renderItems, data): if not self.fPath.isValid(): return ## here, fPath is the path of the linked object instead of the plugin node; it ## is used to determine the right type of the geometry shape, e.g., polygon ## or NURBS surface. ## The sharing flag (true here) is just for the polygon shape. options = omr.MGeometryExtractor.kPolyGeom_Normal if self.isBaseMesh(): options = options | omr.MGeometryExtractor.kPolyGeom_BaseMesh extractor = omr.MGeometryExtractor(requirements, self.fPath, options) if extractor is None: return ## fill vertex buffer descList = requirements.vertexRequirements() for desc in descList: if desc.semantic == omr.MGeometry.kPosition or desc.semantic == omr.MGeometry.kPosition or desc.semantic == omr.MGeometry.kNormal or desc.semantic == omr.MGeometry.kTexture or desc.semantic == omr.MGeometry.kTangent or desc.semantic == omr.MGeometry.kBitangent or desc.semantic == omr.MGeometry.kColor: vertexBuffer = data.createVertexBuffer(desc) if vertexBuffer is not None: ## MGeometryExtractor.vertexCount and MGeometryExtractor.populateVertexBuffer. ## since the plugin node has the same vertex data as its linked scene object, ## call vertexCount to allocate vertex buffer of the same size, and then call ## populateVertexBuffer to copy the data. vertexCount = extractor.vertexCount() vertices = vertexBuffer.acquire(vertexCount, True) ## writeOnly - we don't need the current buffer values if vertices is not None: extractor.populateVertexBuffer(vertices, vertexCount, desc) vertexBuffer.commit(vertices) ## fill index buffer for item in renderItems: indexBuffer = data.createIndexBuffer(omr.MGeometry.kUnsignedInt32) if indexBuffer is None: continue ## MGeometryExtractor.primitiveCount and MGeometryExtractor.populateIndexBuffer. ## since the plugin node has the same index data as its linked scene object, ## call primitiveCount to allocate index buffer of the same size, and then call ## populateIndexBuffer to copy the data. if item.primitive() == omr.MGeometry.kTriangles: triangleDesc = omr.MIndexBufferDescriptor(omr.MIndexBufferDescriptor.kTriangle, "", omr.MGeometry.kTriangles, 3) numTriangles = extractor.primitiveCount(triangleDesc) indices = indexBuffer.acquire(3 * numTriangles, True) ## writeOnly - we don't need the current buffer values extractor.populateIndexBuffer(indices, numTriangles, triangleDesc) indexBuffer.commit(indices) elif item.primitive() == omr.MGeometry.kLines: edgeDesc = omr.MIndexBufferDescriptor(omr.MIndexBufferDescriptor.kEdgeLine, "", omr.MGeometry.kLines, 2) numEdges = extractor.primitiveCount(edgeDesc) indices = indexBuffer.acquire(2 * numEdges, True) ## writeOnly - we don't need the current buffer values extractor.populateIndexBuffer(indices, numEdges, edgeDesc) indexBuffer.commit(indices) item.associateWithIndexBuffer(indexBuffer)
def __init__(self, name): # type: (Text) -> None self.operatioIndex = 0 self.operations = [ omr.MSceneRender("scene"), ManipulatorSceneRender("manipulatorRender"), omr.MHUDRender(), omr.MPresentTarget("present") ] self.operations[0].clearOperation().setOverridesColors(False) super(DrawManipulatorOverride, self).__init__(name)
def initialize(self, shader): # Retrieve and cache the actual node pointer if not shader.isNull(): self.fShaderNode = omui.MPxHwShaderNode.getHwShaderNode(shader) # Set position requirement reqName = "" self.addGeometryRequirement(omr.MVertexBufferDescriptor(reqName, omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)) # Set correct color requirement if self.fShaderNode is not None: reqName = self.fShaderNode.colorSetName() self.addGeometryRequirement(omr.MVertexBufferDescriptor(reqName, omr.MGeometry.kColor, omr.MGeometry.kFloat, 4)) return "Autodesk Maya hwColorPerVertexShader"
def getCustomSemantics(): if OpenMayaRender.drawAPI() == OpenMayaRender.MRenderer.kDirectX11: # register a generator based on a custom semantic for DX11. # You can use any name in DX11. return ('myCustomStream', 'muCustomStreamB') if OpenMayaRender.MRenderer.drawAPI( ) == OpenMayaRender.MRenderer.kOpenGLCoreProfile: # register a generator based on a custom semantic for OGSFX. # Pretty limited in OGSFX since it only allows standard semantics. # but thanks to the annotations a custom value can be set afterward from glslShader plugin return ('myCustomStream', 'myCustomStreamB') if OpenMayaRender.MRenderer.drawAPI() == OpenMayaRender.MRenderer.kOpenGL: # register a generator based on a custom semantic for cg. # Pretty limited in cg so we hook onto the ATTR semantics return ('ATTR8', 'ATTR7')
def draw(self, context, renderItemList): ##-------------------------- ## Matrix set up ##-------------------------- ## Set world view matrix glMatrixMode(GL_MODELVIEW) glPushMatrix() transform = context.getMatrix(omr.MFrameContext.kWorldViewMtx) glLoadMatrixd(matrixAsArray(transform)) ## Set projection matrix glMatrixMode(GL_PROJECTION) glPushMatrix() projection = context.getMatrix(omr.MFrameContext.kProjectionMtx) glLoadMatrixd(matrixAsArray(projection)) ##-------------------------- ## State set up ##-------------------------- stateMgr = context.getStateManager() ## Blending ## Save current blend status curBlendState = stateMgr.getBlendState() if curBlendState is None: return False if self.fBlendState is None: ## If we haven't got a blending state, then acquire a new one. ## Since it would be expensive to acquire the state, we would ## store it. ## Create a new blend status and acquire blend state from the context blendDesc = omr.MBlendStateDesc() for i in range(omr.MBlendState.kMaxTargets): blendDesc.targetBlends[i].blendEnable = True blendDesc.targetBlends[ i].sourceBlend = omr.MBlendState.kSourceAlpha blendDesc.targetBlends[ i].destinationBlend = omr.MBlendState.kInvSourceAlpha blendDesc.targetBlends[i].blendOperation = omr.MBlendState.kAdd blendDesc.targetBlends[ i].alphaSourceBlend = omr.MBlendState.kOne blendDesc.targetBlends[ i].alphaDestinationBlend = omr.MBlendState.kInvSourceAlpha blendDesc.targetBlends[ i].alphaBlendOperation = omr.MBlendState.kAdd blendDesc.blendFactor = (1.0, 1.0, 1.0, 1.0) self.fBlendState = stateMgr.acquireBlendState(blendDesc) if self.fBlendState is None: return False ## Activate the blend on the device stateMgr.setBlendState(self.fBlendState) ## Bounding box draw if self.fShaderNode.wantDrawBoundingBox(): for renderItem in renderItemList: if renderItem is None: continue ## Modelview matrix is already set so just use the object ## space bbox. box = renderItem.boundingBox(om.MSpace.kObject) ## Draw the bounding box. wireColor = om.MColor((0.1, 0.15, 0.35)) drawBoundingBox(box, wireColor) ##-------------------------- ## geometry draw ##-------------------------- useCustomDraw = False if useCustomDraw: ## Custom draw ## Does not set state, matrix or material self.customDraw(context, renderItemList) else: ## Internal standard draw ## Does not set state, matrix or material self.drawGeometry(context) ##-------------------------- ## Matrix restore ##-------------------------- glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() ##-------------------------- ## State restore ##-------------------------- ## Restore blending stateMgr.setBlendState(curBlendState) return True
def __init__(self, name): if kDebugAll or kDebugRenderOverride: print("Initializing viewRenderOverride") #omr.MRenderOverride.__init__(self, name) super(viewRenderOverride, self).__init__(name) # name in the renderer dropdown menu self.mUIName = kPluginName # everytime you are preparing a plate, # you have to count which step you are on # this is reset when you start a new plate self.mOperation = 0 # label for the onion # current frame, used for setting the onion target key self.mCurrentFrame = 0 # holds all avaialable onions # the key to the target is its frame number self.mOnionBuffer = {} # sometimes M doesn't want to see onions, # thats when this should be False self.mEnableBlend = False # save the relative Onions self.mRelativeOnions = {} # save the absolute onions self.mAbsoluteOnions = {} # save all the objects to display in a list self.mOnionObjectList = om.MSelectionList() # store the render operations that combine onions in a list self.mRenderOperations = [] # the tints for onions self.mRelativeFutureTint = [255, 0, 0] self.mRelativePastTint = [0, 255, 0] self.mAbsoluteTint = [0, 0, 255] # tint strengths, 1 is full tint self.mRelativeTintStrength = 1.0 self.mAbsoluteTintStrength = 1.0 # If this is True, we will show onions on the next keyticks # e.g. if mRelativeOnions has 1 and 3 in it, it will draw # the next and the 3rd frame with a tick on the timeslider self.mRelativeKeyDisplay = True self.mCallbackId = 0 # Passes self.mClearPass = viewRenderClearRender("clearPass") self.mClearPass.setOverridesColors(False) self.mRenderOperations.append(self.mClearPass) self.mStandardPass = viewRenderSceneRender( "standardPass", omr.MClearOperation.kClearNone) self.mRenderOperations.append(self.mStandardPass) self.mOnionPass = viewRenderSceneRender("onionPass", omr.MClearOperation.kClearAll) self.mOnionPass.setSceneFilter(omr.MSceneRender.kRenderShadedItems) self.mOnionPass.setDrawSelectionFilter(True) self.mRenderOperations.append(self.mOnionPass) self.mHUDPass = viewRenderHUDRender() self.mRenderOperations.append(self.mHUDPass) self.mPresentTarget = viewRenderPresentTarget("presentTarget") self.mRenderOperations.append(self.mPresentTarget) # TARGETS # standard target is what will be displayed. all but onion render to this target self.mStandardTargetDescr = omr.MRenderTargetDescription() self.mStandardTargetDescr.setName("standardTarget") self.mStandardTargetDescr.setRasterFormat( omr.MRenderer.kR8G8B8A8_UNORM) # onion target will be blended over standard target self.mOnionTargetDescr = omr.MRenderTargetDescription() self.mOnionTargetDescr.setName("onionTarget") self.mOnionTargetDescr.setRasterFormat(omr.MRenderer.kR8G8B8A8_UNORM) # Set the targets that don't change self.mTargetMgr = omr.MRenderer.getRenderTargetManager() self.mStandardTarget = self.mTargetMgr.acquireRenderTarget( self.mStandardTargetDescr) self.mClearPass.setRenderTarget(self.mStandardTarget) self.mStandardPass.setRenderTarget(self.mStandardTarget) self.mHUDPass.setRenderTarget(self.mStandardTarget) self.mPresentTarget.setRenderTarget(self.mStandardTarget)
def draw(context, data): ## Get user draw data footData = data if not isinstance(footData, footPrintData): return ## Get DAG object draw override objectOverrideInfo = footData.fDrawOV ## Sample code to determine the rendering destination debugDestination = False if debugDestination: destination = context.renderingDestination() destinationType = "3d viewport" if destination[0] == omr.MFrameContext.k2dViewport: destinationType = "2d viewport" elif destination[0] == omr.MFrameContext.kImage: destinationType = "image" print "footprint node render destination is " + destinationType + ". Destination name=" + str( destination[1]) ## Just return and draw nothing, if it is overridden invisible if objectOverrideInfo.overrideEnabled and not objectOverrideInfo.enableVisible: return ## Get display status displayStyle = context.getDisplayStyle() drawAsBoundingbox = (displayStyle & omr.MFrameContext.kBoundingBox ) or (objectOverrideInfo.lod == om.MDAGDrawOverrideInfo.kLODBoundingBox) ## If we don't want to draw the bounds within this plugin ## manually, then skip drawing altogether in bounding box mode ## since the bounds draw is handled by the renderer and ## doesn't need to be drawn here. ## if drawAsBoundingbox and not footData.fCustomBoxDraw: return animPlay = oma.MAnimControl.isPlaying() animScrub = oma.MAnimControl.isScrubbing() ## If in playback but hidden in playback, skip drawing if (animPlay or animScrub) and not objectOverrideInfo.playbackVisible: return ## For any viewport interactions switch to bounding box mode, ## except when we are in playback. if context.inUserInteraction() or context.userChangingViewContext(): if not animPlay and not animScrub: drawAsBoundingbox = True ## Now, something gonna draw... ## Check to see if we are drawing in a shadow pass. ## If so then we keep the shading simple which in this ## example means to disable any extra blending state changes ## passCtx = context.getPassContext() passSemantics = passCtx.passSemantics() castingShadows = False for semantic in passSemantics: if semantic == omr.MPassContext.kShadowPassSemantic: castingShadows = True debugPassInformation = False if debugPassInformation: passId = passCtx.passIdentifier() print "footprint node drawing in pass[" + str( passId) + "], semantic[" + str(passSemantics) + "]" ## get cached data multiplier = footData.fMultiplier color = [ footData.fColor[0], footData.fColor[1], footData.fColor[2], 1.0 ] requireBlending = False ## If we're not casting shadows then do extra work ## for display styles if not castingShadows: ## Use some monotone version of color to show "default material mode" ## if displayStyle & omr.MFrameContext.kDefaultMaterial: color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0 ## Do some alpha blending if in x-ray mode ## elif displayStyle & omr.MFrameContext.kXray: requireBlending = True color[3] = 0.3 ## Set blend and raster state ## stateMgr = context.getStateManager() oldBlendState = None oldRasterState = None rasterStateModified = False if stateMgr is not None and (displayStyle & omr.MFrameContext.kGouraudShaded): ## draw filled, and with blending if required if requireBlending: global blendState if blendState is None: desc = omr.MBlendStateDesc() desc.targetBlends[0].blendEnable = True desc.targetBlends[ 0].destinationBlend = omr.MBlendStatekInvSourceAlpha desc.targetBlends[ 0].alphaDestinationBlend = omr.MBlendStatekInvSourceAlpha blendState = stateMgr.acquireBlendState(desc) if blendState is not None: oldBlendState = stateMgr.getBlendState() stateMgr.setBlendState(blendState) ## Override culling mode since we always want double-sided ## oldRasterState = stateMgr.getRasterizerState() if oldRasterState: desc = oldRasterState.desc() ## It's also possible to change this to kCullFront or kCullBack if we ## wanted to set it to that. cullMode = omr.MRasterizerState.kCullNone if desc.cullMode != cullMode: global rasterState if rasterState is None: ## Just override the cullmode desc.cullMode = cullMode rasterState = stateMgr.acquireRasterizerState(desc) if rasterState is not None: rasterStateModified = True stateMgr.setRasterizerState(rasterState) ##======================== ## Start the draw work ##======================== ## Prepare draw agent, default using OpenGL global drawAgent if drawAgent is None: if omr.MRenderer.drawAPIIsOpenGL(): drawAgent = footPrintDrawAgentGL() else: drawAgent = footPrintDrawAgentDX() if not drawAgent is None: drawAgent.beginDraw(context, color, multiplier) if drawAsBoundingbox: drawAgent.drawBoundingBox(context) else: ## Templated, only draw wirefame and it is not selectale overideTemplated = objectOverrideInfo.overrideEnabled and objectOverrideInfo.displayType == om.MDAGDrawOverrideInfo.kDisplayTypeTemplate ## Override no shaded, only show wireframe overrideNoShaded = objectOverrideInfo.overrideEnabled and not objectOverrideInfo.enableShading if overideTemplated or overrideNoShaded: drawAgent.drawWireframe(context) else: if (displayStyle & omr.MFrameContext.kGouraudShaded) or ( displayStyle & omr.MFrameContext.kTextured): drawAgent.drawShaded(context) if (displayStyle & omr.MFrameContext.kWireFrame): drawAgent.drawWireframe(context) drawAgent.endDraw(context) ##======================== ## End the draw work ##======================== ## Restore old blend state and old raster state if stateMgr is not None and (displayStyle & omr.MFrameContext.kGouraudShaded): if oldBlendState is not None: stateMgr.setBlendState(oldBlendState) if rasterStateModified and oldRasterState is not None: stateMgr.setRasterizerState(oldRasterState)
def initBuffers(self): global soleCount, sole global heelCount, heel if self.mBoundingboxVertexBuffer is None: count = 8 rawData = [[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [-0.5, -0.5, 0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [0.5, 0.5, 0.5], [-0.5, 0.5, 0.5]] desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3) self.mBoundingboxVertexBuffer = omr.MVertexBuffer(desc) dataAddress = self.mBoundingboxVertexBuffer.acquire(count, True) data = ((ctypes.c_float * 3) * count).from_address(dataAddress) for i in range(count): data[i][0] = rawData[i][0] data[i][1] = rawData[i][1] data[i][2] = rawData[i][2] self.mBoundingboxVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mBoundingboxIndexBuffer is None: count = 24 rawData = [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] self.mBoundingboxIndexBuffer = omr.MIndexBuffer( omr.MGeometry.kUnsignedInt32) dataAddress = self.mBoundingboxIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mBoundingboxIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleVertexBuffer is None: desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3) self.mSoleVertexBuffer = omr.MVertexBuffer(desc) dataAddress = self.mSoleVertexBuffer.acquire(soleCount, True) data = ((ctypes.c_float * 3) * soleCount).from_address(dataAddress) for i in range(soleCount): data[i][0] = sole[i][0] data[i][1] = sole[i][1] data[i][2] = sole[i][2] self.mSoleVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelVertexBuffer is None: desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3) self.mHeelVertexBuffer = omr.MVertexBuffer(desc) dataAddress = self.mHeelVertexBuffer.acquire(heelCount, True) data = ((ctypes.c_float * 3) * heelCount).from_address(dataAddress) for i in range(heelCount): data[i][0] = heel[i][0] data[i][1] = heel[i][1] data[i][2] = heel[i][2] self.mHeelVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleWireIndexBuffer is None: count = 2 * (soleCount - 1) rawData = [ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20 ] self.mSoleWireIndexBuffer = omr.MIndexBuffer( omr.MGeometry.kUnsignedInt32) dataAddress = self.mSoleWireIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mSoleWireIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelWireIndexBuffer is None: count = 2 * (heelCount - 1) rawData = [ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 ] self.mHeelWireIndexBuffer = omr.MIndexBuffer( omr.MGeometry.kUnsignedInt32) dataAddress = self.mHeelWireIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mHeelWireIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleShadedIndexBuffer is None: count = 3 * (soleCount - 2) rawData = [ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16, 0, 16, 17, 0, 17, 18, 0, 18, 19, 0, 19, 20 ] self.mSoleShadedIndexBuffer = omr.MIndexBuffer( omr.MGeometry.kUnsignedInt32) dataAddress = self.mSoleShadedIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mSoleShadedIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelShadedIndexBuffer is None: count = 3 * (heelCount - 2) rawData = [ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16 ] self.mHeelShadedIndexBuffer = omr.MIndexBuffer( omr.MGeometry.kUnsignedInt32) dataAddress = self.mHeelShadedIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mHeelShadedIndexBuffer.commit(dataAddress) dataAddress = None data = None return True
def initBuffers(self): global soleCount, sole global heelCount, heel #EXPLANATION: VERTEX BUFFERS and INDEX BUFFERS Maya API: # https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-SDK/files/GUID-148A1EF1-B350-416F-A800-C47DA90D1369-htm.html if self.mBoundingBoxVertexBuffer is None: count = 8 rawData = [[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [-0.5, -0.5, 0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [0.5, 0.5, 0.5], [-0.5, 0.5, 0.5]] desc = OpenMayaRender.MVertexBufferDescriptor( '', OpenMayaRender.MGeometry.kPosition, OpenMayaRender.MGeometry.kFloat, 3) self.mBoundingBoxVertexBuffer = OpenMayaRender.MVertexBuffer(desc) dataAddress = self.mBoundingBoxVertexBuffer.acquire(count, True) # is a foreign function library for Python. # It provides C compatible data types, and allows calling functions in DLLs or shared libraries. # It can be used to wrap these libraries in pure Python. data = ((ctypes.c_float * 3) * count).from_address(dataAddress) for i in range(count): data[i][0] = rawData[i][0] data[i][1] = rawData[i][1] data[i][2] = rawData[i][2] self.mBoundingBoxVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mBoundingBoxIndexBuffer is None: count = 24 rawData = [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] # buffers EXPLANATION // explain better rawData // raw data is an indexBuffer # here we get a space in memory and the fill it with C Data types # https://vulkan-tutorial.com/Vertex_buffers/Index_buffer <-- indexBuffer EXPLANATION # the indices need to be uploaded to ha vkBuffer for the GPU be able to them # MIndexBuffer represents an index buffer with a specific data. usable with MGeometry self.mBoundingBoxIndexBuffer = OpenMayaRender.MIndexBuffer( OpenMayaRender.MGeometry.kUnsignedInt32) # acquire() may be called to get a pointer to a block of memory to fill with said data. # args: size of the buffer(int) // writeOnly (bool) # Once filled, commit() must be called to apply the data to the buffer. dataAddress = self.mBoundingBoxIndexBuffer.acquire(count, True) # ctypes provides C compatible data types, and allows calling functions in DLLs or shared libraries. # It can be used to wrap these libraries in pure Python. # http://pyplusplus.readthedocs.io/en/latest/tutorials/functions/transformation/from_address.html <-- from_address EXPLANATION # unsigned_int * count -> [c_uint][c_uint]... count times # from_address you can use ctypes package to create the data and than pass it to # the Boost.Python exposed function, in this case dataAddress data = (ctypes.c_uint * count).from_address(dataAddress) # fill our buffer for i in range(count): data[i] = rawData[i] # here is the commit(), once we filled dataAddress with c types through .from_address from data. # Commit the data stored in the memory given by acquire() to the buffer. self.mBoundingBoxIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleVertexBuffer is None: desc = OpenMayaRender.MVertexBufferDescriptor( '', OpenMayaRender.MGeometry.kPosition, OpenMayaRender.MGeometry.kFloat, 3) self.mSoleVertexBuffer = OpenMayaRender.MVertexBuffer(desc) dataAddress = self.mSoleVertexBuffer.acquire(soleCount, True) data = ((ctypes.c_float * 3) * soleCount).from_address(dataAddress) for i in range(soleCount): data[i][0] = sole[i][0] data[i][1] = sole[i][1] data[i][2] = sole[i][2] self.mSoleVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelVertexBuffer is None: desc = OpenMayaRender.MVertexBufferDescriptor( '', OpenMayaRender.MGeometry.kPosition, OpenMayaRender.MGeometry.kFloat, 3) self.mHeelVertexBuffer = OpenMayaRender.MVertexBuffer(desc) dataAddress = self.mHeelVertexBuffer.acquire(heelCount, True) data = ((ctypes.c_float * 3) * heelCount).from_address(dataAddress) for i in range(heelCount): data[i][0] = heel[i][0] data[i][1] = heel[i][1] data[i][2] = heel[i][2] self.mHeelVertexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleWireIndexBuffer is None: count = 2 * (soleCount - 1) rawData = [ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20 ] self.mSoleWireIndexBuffer = OpenMayaRender.MIndexBuffer( OpenMayaRender.MGeometry.kUnsignedInt32) dataAddress = self.mSoleWireIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mSoleWireIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelWireIndexBuffer is None: count = 2 * (heelCount - 1) rawData = [ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 ] self.mHeelWireIndexBuffer = OpenMayaRender.MIndexBuffer( OpenMayaRender.MGeometry.kUnsignedInt32) dataAddress = self.mHeelWireIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mHeelWireIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mSoleShadedIndexBuffer is None: count = 3 * (soleCount - 2) rawData = [ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16, 0, 16, 17, 0, 17, 18, 0, 18, 19, 0, 19, 20 ] self.mSoleShadedIndexBuffer = OpenMayaRender.MIndexBuffer( OpenMayaRender.MGeometry.kUnsignedInt32) dataAddress = self.mSoleShadedIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mSoleShadedIndexBuffer.commit(dataAddress) dataAddress = None data = None if self.mHeelShadedIndexBuffer is None: count = 3 * (heelCount - 2) rawData = [ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16 ] self.mHeelShadedIndexBuffer = OpenMayaRender.MIndexBuffer( OpenMayaRender.MGeometry.kUnsignedInt32) dataAddress = self.mHeelShadedIndexBuffer.acquire(count, True) data = (ctypes.c_uint * count).from_address(dataAddress) for i in range(count): data[i] = rawData[i] self.mHeelShadedIndexBuffer.commit(dataAddress) dataAddress = None data = None return True
def __init__(self, name): if DEBUG: print ("Initializing ViewRenderOverride") #omr.MRenderOverride.__init__(self, name) super(ViewRenderOverride, self).__init__(name) # name in the renderer dropdown menu self.UIName = PLUGIN_NAME # this counts through the render passes # restarts for every frame output to the screen self.operation = 0 # label for the onion # current frame, used for setting the onion target key self.currentFrame = 0 # holds all avaialable onion skin renders # the key to the target is its frame number self.onionSkinBuffer = {} # save the order in which onions where added self.onionSkinBufferQueue = collections.deque() # max amount of buffered frames self.maxOnionSkinBufferSize = 200 # store blend passes for relative onion skin display # a pass is stored when the user activates it in the ui with the "v" icon self.relativeBlendPasses = {} # only display every nth relative onion self.relativeStep = 1 # store blend passes for absolute onion skin display # a blend pass is stored with the key being its frame # a blend pass is added for each absolute onion skin display the user registers self.absoluteBlendPasses = {} # buffer onion objects to make adding sets possible self.onionObjectBuffer = om.MSelectionList() # save all the objects to display in a list self.onionObjectList = om.MSelectionList() # store the render operations that combine onions in a list self.renderOperations = [] # tint colors for different os types rgb 0-255 self.relativeFutureTint = [255,0,0] self.relativePastTint = [0,255,0] self.absoluteTint = [0,0,255] # tint strengths, 1 is full tint self.tintStrength = 1.0 self.globalOpacity = 1.0 self.onionSkinDisplayType = 1 # outline width in pixels self.outlineWidth = 3 self.drawBehind = 1 # range 0-2. # 0 = default, 1 = relative random, 2 = static random self.tintType = 0 # seed value set by user to get different random colors for tints self.tintSeed = 0 # If this is True, we will show onion skins on the next keyticks # e.g. if relativeBlendPasses has 1 and 3 in it, it will draw # the next and the 3rd frame with a tick on the timeslider self.relativeKeyDisplay = True # self.timeCallbackId = 0 # self.cameraMovedCallbackIds = [] # self.autoClearBuffer = True # Passes self.clearPass = clearRender.viewRenderClearRender("clearPass") self.clearPass.setOverridesColors(False) self.renderOperations.append(self.clearPass) self.standardPass = sceneRender.OSSceneRender( "standardPass", omr.MClearOperation.kClearNone ) self.renderOperations.append(self.standardPass) # the onion skin pass buffers an image of the specified object on the current frame self.onionSkinPass = sceneRender.OSSceneRender( "onionSkinPass", omr.MClearOperation.kClearAll ) self.onionSkinPass.setSceneFilter(omr.MSceneRender.kRenderShadedItems) self.onionSkinPass.setDrawSelectionFilter(True) self.renderOperations.append(self.onionSkinPass) self.HUDPass = hudRender.viewRenderHUDRender() self.renderOperations.append(self.HUDPass) self.presentTarget = presentTarget.viewRenderPresentTarget("presentTarget") self.renderOperations.append(self.presentTarget) # TARGETS # standard target is what will be displayed. all but onion skins render to this target self.standardTargetDescr = omr.MRenderTargetDescription() self.standardTargetDescr.setName("standardTarget") self.standardTargetDescr.setRasterFormat(omr.MRenderer.kR8G8B8A8_UNORM) self.depthTargetDescr = omr.MRenderTargetDescription() self.depthTargetDescr.setName("depthTarget") self.depthTargetDescr.setRasterFormat(omr.MRenderer.kD24S8) # with this onion skins will be blended over standard target self.blendTargetDescr = omr.MRenderTargetDescription() self.blendTargetDescr.setName("onionTarget") self.blendTargetDescr.setRasterFormat(omr.MRenderer.kR8G8B8A8_UNORM) # Set the targets that don't change self.targetMgr = omr.MRenderer.getRenderTargetManager() self.standardTarget = self.targetMgr.acquireRenderTarget(self.standardTargetDescr) self.clearPass.setRenderTarget(self.standardTarget) self.standardPass.setRenderTarget(self.standardTarget) self.HUDPass.setRenderTarget(self.standardTarget) self.presentTarget.setRenderTarget(self.standardTarget)