def deform(self, dataBlock, geomIter, matrix, multiIndex): # get input mesh hInput = dataBlock.outputArrayValue(self.input) hInput.jumpToElement(multiIndex) hInputGeom = hInput.outputValue().child(self.inputGeom) oInputGeom = hInputGeom.asMesh() fnPoint = OpenMaya.MFnMesh(oInputGeom) # attribute handles hDivide = dataBlock.inputValue(self.aDivide) hVertex = dataBlock.inputArrayValue(self.aVertex) hDistance = dataBlock.outputArrayValue(self.aDistance) # attribute values vDivide = hDivide.asFloat() # MArrayDataBuilder: # value of third argument (numElements) does not seem to matter (in Python ?!) dbDistance = OpenMaya.MArrayDataBuilder(dataBlock, self.aDistance, hVertex.elementCount()) # calculate (loop through vertex 2D-array) for x in range(hVertex.elementCount()): hVertex.jumpToArrayElement(x) # get vertices iVtx0, iVtx1 = hVertex.inputValue().asInt2() p1 = OpenMaya.MPoint() p2 = OpenMaya.MPoint() fnPoint.getPoint(iVtx0, p1, OpenMaya.MSpace.kWorld) fnPoint.getPoint(iVtx1, p2, OpenMaya.MSpace.kWorld) # calculate distance vecP1toP2 = OpenMaya.MVector(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z) fDistance = vecP1toP2.length() / vDivide # set distance hDistanceBuilder = dbDistance.addElement(hVertex.elementIndex()) hDistanceBuilder.setFloat(fDistance) hDistance.set(dbDistance)
def compute(self, plug, dataBlock): if plug == arrayTest.output1WgtAttr: #calculations here #get inputs dataHandleInput = dataBlock.inputValue(arrayTest.input1VecAttr) inVal = dataHandleInput.asFloat() #get ouput array arrayDataHandle = OpenMaya.MArrayDataHandle( dataBlock.outputArrayValue(arrayTest.output1WgtAttr)) myBuilder = OpenMaya.MArrayDataBuilder(arrayTest.output1WgtAttr, 0) for i in range(arrayDataHandle.elementCount()): #arrayDataHandle.next() output = inVal / (i + 1) #output = inVal + outValue myElementHandle = OpenMaya.MDataHandle(myBuilder.addElement(i)) myElementHandle.setFloat(output) arrayDataHandle.set(myBuilder) arrayDataHandle.setAllClean() dataBlock.setClean(plug) else: return OpenMaya.kUnknownParameter
def MVectorsToNodeAttr(DataBlock, NodeAttr, Mvectors): builder = om.MArrayDataBuilder(DataBlock, NodeAttr, len(Mvectors)) for i in range(0, len(Mvectors)): handle = builder.addElement(i) handle.setMFloatVector(Mvectors[i]) arrayDataHandle = DataBlock.outputArrayValue(NodeAttr) arrayDataHandle.set(builder) arrayDataHandle.setAllClean()
def utils_MMatricesToNodeAttr( self , DataBlock , NodeAttr , Mmatices ): print('utils_MMatricesToNodeAttr') arrayDataHandle = DataBlock.outputArrayValue( NodeAttr ) builder = om.MArrayDataBuilder(DataBlock, NodeAttr, len(Mmatices)) print(builder.elementCount()) for i in range(0, len(Mmatices) ): handle = builder.addElement(i) print( builder.elementCount() , utils_MMatrixToNum(Mmatices[i]) ) handle.setMMatrix( Mmatices[i] ) arrayDataHandle.set(builder) arrayDataHandle.setAllClean()
def initVertMapping(self, data, iter, localToWorldMatrix, mIndex): #make poly mesh function set object: meshAttrHandle = data.inputValue(self.driver_mesh) meshMobj = meshAttrHandle.asMesh() vertIter = OpenMaya.MItMeshVertex(meshMobj) vertIter.reset() count = iter.count() vertMapOutArrayData = data.outputArrayValue(self.vert_map) vertMapOutArrayBuilder = OpenMaya.MArrayDataBuilder( self.vert_map, count) allPts = OpenMaya.MPointArray() allPts.clear() i = 0 #first initialize all mappings to -1, and also store a buffer pt array to search through: while (iter.isDone() == False): initIndexDataHnd = vertMapOutArrayBuilder.addElement(i) negIndex = -1 initIndexDataHnd.setInt(negIndex) initIndexDataHnd.setClean() allPts.append(iter.position() * localToWorldMatrix) i = i + 1 iter.next() vertMapOutArrayData.set(vertMapOutArrayBuilder) while (vertIter.isDone() == False): driver_pt = OpenMaya.MPoint() driver_pt = vertIter.position(OpenMaya.MSpace.kWorld) closest_pt_index = self.getClosestPt(driver_pt, allPts) #save the closest point mapping to snap verts to each other here: snapDataHnd = vertMapOutArrayBuilder.addElement(closest_pt_index) snapDataHnd.setInt(vertIter.index()) snapDataHnd.setClean() vertIter.next() vertMapOutArrayData.set(vertMapOutArrayBuilder) tObj = self.thisMObject() setInitMode = OpenMaya.MPlug(tObj, self.initialized_data) setInitMode.setShort(2) iter.reset( ) #important, reset the geom iterator so it starts from zero again
def set_inverted_from_tweak(self, data_block): """ Update .inverted_tweak_attr from the current value of .tweak. """ tweak_data = data_block.inputArrayValue(self.tweak_attr) matrices = self.get_matrices(data_block) outputInvertedTweak = data_block.outputArrayValue(self.inverted_tweak_attr) # Don't use outputInvertedTweak.builder(). That'll return a builder containing # the existing data of the plug. If there are tweak indexes that are now (0,0,0) # which used to have data, we'd need to remove them in the short-circuit case # below, and there's no fast way to do that. Create a new builder instead. # builder = outputInvertedTweak.builder() builder = OpenMaya.MArrayDataBuilder(data_block, self.inverted_tweak_attr, 0) # Always add an element at index 0, or compute() will be called every frame. # This seems like a quirk of the tweak connection. newElement = builder.addElement(0) newElement.set3Float(0,0,0) for item in iterate_array_handle(tweak_data): thisValue = tweak_data.inputValue() delta = thisValue.asFloat3() # Skip zero tweaks. Most blend shapes will have small, localized changes to # some part of the mesh, so we save a lot of time by not processing vertices # that haven't been changed. This also saves time during MPxGeometryFilter_outputGeom # calculation, since that also won't spend any time deforming unchanged vertices. if abs(delta[0]) < 0.001 and abs(delta[1]) < 0.001 and abs(delta[2]) < 0.001: continue delta = OpenMaya.MVector(*delta) idx = array_current_index(tweak_data) if idx < len(matrices): delta *= matrices[idx] newElement = builder.addElement(idx) newElement.set3Float(*delta) outputInvertedTweak.set(builder) outputInvertedTweak.setAllClean() data_block.setClean(self.inverted_tweak_attr)
def remap(self, data, iter, localToWorldMatrix, mIndex): # check what kind of bind we want to perform # worldspace or uv based transferType = data.inputValue(self.transferType).asShort() meshAttrHandle = data.inputValue(self.inputMesh) driverMesh = meshAttrHandle.asMesh() driverVtxIter = om.MItMeshVertex(driverMesh) driverMFnMesh = om.MFnMesh(driverMesh) vtxMappingArrayData = data.outputArrayValue(self.vertexMapping) vtxMapOutArrayBuilder = om.MArrayDataBuilder(self.vertexMapping, iter.count()) indexArray = om.MPointArray() inputAttribute = omMPx.cvar.MPxGeometryFilter_input inputGeometryAttribute = omMPx.cvar.MPxGeometryFilter_inputGeom inputHandle = data.outputArrayValue(inputAttribute) inputHandle.jumpToElement(mIndex) drivenMesh = inputHandle.outputValue().child( inputGeometryAttribute).asMesh() drivenVtxIter = om.MItMeshVertex(drivenMesh) driven = om.MFnMesh(drivenMesh) if transferType == 0: u, v = om.MFloatArray(), om.MFloatArray() driverUvs = driverMFnMesh.getUVs(u, v) sortedDriverUvs = map(list, zip(u, v)) while not drivenVtxIter.isDone(): drivenIndex = drivenVtxIter.index() vtxMapDataHandler = vtxMapOutArrayBuilder.addElement( drivenIndex) vtxMapDataHandler.setInt(-1) vtxMapDataHandler.setClean() drivenVtxIter.next() drivenVtxIter.reset() driverMapped = {} while not driverVtxIter.isDone(): u, v = self.getMeshUVAtIndex(driverVtxIter) driverIndex = int(driverVtxIter.index()) uvKey = str([u, v]) driverMapped.update({uvKey: driverIndex}) driverVtxIter.next() drivenVtxIter.reset() while not drivenVtxIter.isDone(): drivenIndex = drivenVtxIter.index() d_u, d_v = self.getMeshUVAtIndex(drivenVtxIter) driven_uv = [d_u, d_v] if driven_uv in sortedDriverUvs: if driverMapped.has_key(str(driven_uv)): driverIndex = driverMapped[str(driven_uv)] vtxMapDataHandler = vtxMapOutArrayBuilder.addElement( drivenIndex) vtxMapDataHandler.setInt(driverIndex) vtxMapDataHandler.setClean() drivenVtxIter.next() drivenVtxIter.reset() vtxMappingArrayData.set(vtxMapOutArrayBuilder) elif transferType == 1: return setInitMode = om.MPlug(self.thisMObject(), self.initilizeData) setInitMode.setShort(2)
def initOrigin(self, data, iter, localToWorldMatrix, mIndex): # get the handle for the driver mesh meshAttrHandle = data.inputValue(self.driver_mesh) # get mfnmesh meshMobj = meshAttrHandle.asMesh() meshVerItFn = OpenMaya.MItMeshVertex(meshMobj) meshVerItFn.reset() bind_count = meshVerItFn.count() bindOutArrayData = data.outputArrayValue(self.bindData) bindOutArrayBuilder = OpenMaya.MArrayDataBuilder( self.bindData, bind_count) # get the origin points origin_points = [] i = 0 while not meshVerItFn.isDone(): wsPoint = meshVerItFn.position( OpenMaya.MSpace.kWorld) # * localToWorldMatrix # origin_points.append(np.array([wsPoint.x, wsPoint.y, wsPoint.z])) bindDataHnd = bindOutArrayBuilder.addElement(i) bindDataHnd.set3Float(wsPoint.x, wsPoint.y, wsPoint.z) bindDataHnd.setClean() i += 1 meshVerItFn.next() bindOutArrayData.set(bindOutArrayBuilder) origin_m = np.array(origin_points) # shuffle array inputdata = [] for value_A in origin_m.T: sort_array = [] for value_B in origin_m.T: sort_array.append(value_B) sort_array.append(value_A) inputdata.append(np.array([sort_array])) # create rbfs rbfs = [ Rbf(value[0][0], value[0][1], value[0][2], value[0][3]) for value in inputdata ] # get target points target_points = [] while not iter.isDone(): wsPoint = iter.position() * localToWorldMatrix #localToWorldMatrix target_points.append(np.array([wsPoint.x, wsPoint.y, wsPoint.z])) iter.next() target_m = np.array(target_points) delta_count = iter.count() deltaOutArrayData = data.outputArrayValue(self.deltaData) deltaOutArrayBuilder = OpenMaya.MArrayDataBuilder( self.deltaData, delta_count) for i, target in enumerate(target_m): output = [rbf(*target) for rbf in rbfs] delta = np.round((output - target), 4) deltaDataHnd = deltaOutArrayBuilder.addElement(i) deltaDataHnd.set3Float(float(delta[0]), float(delta[1]), float(delta[2])) deltaDataHnd.setClean() deltaOutArrayData.set(deltaOutArrayBuilder) tObj = self.thisMObject() setInitMode = OpenMaya.MPlug(tObj, self.initialized_data) setInitMode.setShort(2) iter.reset()