def compute(self, plug, block): # カスタムアトリビュートのハンドルを取得 sVal = block.inputValue(self.sVal).asDouble() origMesh = block.inputValue(self.origMesh).asMesh() targetMesh = block.inputValue(self.targetMesh).asMesh() cacheOriEdgeLenHandle = block.outputArrayValue(self.cacheOriEdgeLen) outMeshHandle = block.outputValue(self.outputMesh) # イテレータを取得 origEdgeIter = OM.MItMeshEdge(origMesh) targetEdgeIter = OM.MItMeshEdge(targetMesh) origFnMesh = OM.MFnMesh(origMesh) tarVerIter = OM.MItMeshVertex(targetMesh) # デフォームメッシュデータを準備 meshObject = OM.MFnMeshData().create() resultMesh = OM.MFnMesh() resultMesh.copy(targetMesh, meshObject) # core if origEdgeIter.count() == targetEdgeIter.count(): # 各エッジの長さをリストにしておく oEdgeLenArray = [] while not origEdgeIter.isDone(): oEdgeLenArray.append(origEdgeIter.length()) origEdgeIter.next() tEdgeLenArray = [] while not targetEdgeIter.isDone(): tEdgeLenArray.append(targetEdgeIter.length()) targetEdgeIter.next() # デフォーム while not tarVerIter.isDone(): edgePack = tarVerIter.getConnectedEdges() val = 0.0 oVal = 0.0 tVal = 0.0 for edge in edgePack: oVal += oEdgeLenArray[edge] tVal += tEdgeLenArray[edge] val = 1.0 - tVal / oVal if val < 0.0: curveAttribute = OM.MRampAttribute(self.thisMObject(), self.curveRamp) i = tarVerIter.index() ratio = sVal - abs(origFnMesh.getPoint(i).y) / sVal val *= curveAttribute.getValueAtPosition(ratio) offset = tarVerIter.getNormal() * val resultMesh.setPoint(tarVerIter.index(), tarVerIter.position() + offset) tarVerIter.next() # メッシュを出力 outMeshHandle.setMObject(meshObject) # 終了宣言 block.setClean(plug)
def compute(self, plug, block): # カスタムアトリビュートのハンドルを取得 follow = block.inputValue(self.follow).asDouble() restore = block.inputValue(self.restore).asDouble() time = block.inputValue(self.time).asDouble() pos = block.inputValue(self.pos).asVector() origMesh = block.inputValue(self.origMesh).asMesh() posResHandle = block.outputValue(self.positionRest) velResHandle = block.outputValue(self.velocityRest) outMeshHandle = block.outputValue(self.outputMesh) # イテレータを取得 origVerIter = OM.MItMeshVertex(origMesh) # デフォームメッシュデータを準備 meshObject = OM.MFnMeshData().create() resultMesh = OM.MFnMesh() resultMesh.copy(origMesh, meshObject) # core if time == 1.0: # reset velResHandle.set3Double(0, 0, 0) posResHandle.set3Double(0, 0, 0) posRest = posResHandle.asVector() velRest = velResHandle.asVector() newPos = (pos - posRest) * follow vlct = velRest + (newPos - velRest) * restore velResHandle.set3Double(vlct.x, vlct.y, vlct.z) offset = posRest + velRest posResHandle.set3Double(offset.x, offset.y, offset.z) while not origVerIter.isDone(): poiPos = origVerIter.position() + offset resultMesh.setPoint(origVerIter.index(), poiPos) origVerIter.next() # メッシュを出力 outMeshHandle.setMObject(meshObject) # 終了宣言 block.setClean(plug)
def compute(self, pPlug, pDataBlock): ''' Here, we will create a voxelized version of the input mesh. ''' if (pPlug == VoxelizerNode.outputMeshAttribute): # Get our custom input node attributes and values. voxelWidthHandle = pDataBlock.inputValue( VoxelizerNode.voxelWidthAttribute) voxelWidth = voxelWidthHandle.asFloat() voxelDistanceHandle = pDataBlock.inputValue( VoxelizerNode.voxelDistanceAttribute) voxelDistance = voxelDistanceHandle.asFloat() inputMeshHandle = pDataBlock.inputValue( VoxelizerNode.inputMeshAttribute) inputMeshObj = inputMeshHandle.asMesh() # Compute the bounding box around the mesh vertices. boundingBox = self.getBoundingBox(inputMeshObj) # Determine which voxel centerpoints are contained within the mesh. voxels = self.getVoxels(voxelDistance, inputMeshObj, boundingBox) # Create a mesh data container, which will store our new voxelized mesh. meshDataFn = OpenMaya.MFnMeshData() newOutputMeshData = meshDataFn.create() # Create a cubic polygon for each voxel and populate the 'newOutputMeshData' MeshData object. self.createVoxelMesh(voxels, voxelWidth, newOutputMeshData) # Set the output data. outputMeshHandle = pDataBlock.outputValue( VoxelizerNode.outputMeshAttribute) outputMeshHandle.setMObject(newOutputMeshData) else: return OpenMaya.kUnknownParameter
def compute(self, _plug, _dataBlock): # Check if the plug is the output mesh if (_plug == WarpNodeClass.m_outMesh): # Get handles for the attributes terrainDataHandle = _dataBlock.inputValue(WarpNodeClass.m_terrain) terrainValue = terrainDataHandle.asMesh() maxRadiusDataHandle = _dataBlock.inputValue(WarpNodeClass.m_maxRadius) maxRadiusValue = maxRadiusDataHandle.asFloat() controlPointsDataHandle = _dataBlock.inputArrayValue(WarpNodeClass.m_controlPoints) outMeshDataHandle = _dataBlock.outputValue(WarpNodeClass.m_outMesh) # Get all the vertices from the terrain inTerrainFn = om.MFnMesh(terrainValue) vertexPositions = inTerrainFn.getPoints() if self.m_firstCompute == True: # Get a list of the original control points positions controlPointsOriginalDataHandle = _dataBlock.inputArrayValue(WarpNodeClass.m_controlPointsOriginal) self.m_controlPointsOriginal = [] if (len(controlPointsOriginalDataHandle) > 0): controlPointsOriginalDataHandle.jumpToPhysicalElement(0) while not controlPointsOriginalDataHandle.isDone(): inputDataHandle = controlPointsOriginalDataHandle.inputValue() point = inputDataHandle.asDouble3() self.m_controlPointsOriginal.append(point) controlPointsOriginalDataHandle.next() numControlPoints = len(self.m_controlPointsOriginal) # Calculate the max radius for each control point maxRadiusSquared = maxRadiusValue * maxRadiusValue controlPointsRadii = numControlPoints * [maxRadiusSquared] for i in range(numControlPoints): distances = [] for j in range(numControlPoints): dX = self.m_controlPointsOriginal[i][0] - self.m_controlPointsOriginal[j][0] dZ = self.m_controlPointsOriginal[i][2] - self.m_controlPointsOriginal[j][2] distances.append(dX*dX + dZ*dZ) distances.sort() if distances[3] < maxRadiusSquared: controlPointsRadii[i] = distances[3] # Calculate which vertices are affected for i in range(numControlPoints): tempArray = [] # Calculate the min and max X and Z coordinates minX = self.m_controlPointsOriginal[i][0] - controlPointsRadii[i] maxX = self.m_controlPointsOriginal[i][0] + controlPointsRadii[i] minZ = self.m_controlPointsOriginal[i][2] - controlPointsRadii[i] maxZ = self.m_controlPointsOriginal[i][2] + controlPointsRadii[i] vertexIterator = om.MItMeshVertex(terrainValue) position = om.MPoint() while not vertexIterator.isDone(): position = vertexIterator.position(om.MSpace.kWorld) if minX < position.x < maxX: if minZ < position.z < maxZ: index = vertexIterator.index() dX = self.m_controlPointsOriginal[i][0] - position.x dZ = self.m_controlPointsOriginal[i][2] - position.z distanceSquared = dX * dX + dZ * dZ if distanceSquared < controlPointsRadii[i]: ratio = distanceSquared / controlPointsRadii[i] softSelectValue = 1.0 - ratio tempArray.append((index, softSelectValue)) vertexIterator.next() self.m_controlPointsVertices.append(tempArray) # Set this variable as false so this block of code is never recomputed self.m_firstCompute = False # Get a list of the control points positions controlPoints = [] if (len(controlPointsDataHandle) > 0): controlPointsDataHandle.jumpToPhysicalElement(0) while not controlPointsDataHandle.isDone(): inputDataHandle = controlPointsDataHandle.inputValue() point = inputDataHandle.asDouble3() controlPoints.append(point) controlPointsDataHandle.next() # Compute the difference in positions controlPointsDifference = [] for cp, cpOriginal in zip(controlPoints,self.m_controlPointsOriginal): dX = cp[0] - cpOriginal[0] dY = cp[1] - cpOriginal[1] dZ = cp[2] - cpOriginal[2] controlPointsDifference.append(om.MVector(dX,dY,dZ)) # Move the affected vertices numControlPoints = len(self.m_controlPointsOriginal) for i in range(numControlPoints): for point in self.m_controlPointsVertices[i]: vertexPositions[point[0]] += controlPointsDifference[i] * point[1] # Create a copy of the mesh to output meshDataFn = om.MFnMeshData() outTerrain = meshDataFn.create() outTerrainFn = om.MFnMesh() outTerrainFn.copy(terrainValue, outTerrain) # Set the output vertices outTerrainFn.setPoints(vertexPositions) # Set the output value outMeshDataHandle.setMObject(outTerrain) # Mark the output data handle as clean outMeshDataHandle.setClean()
def compute(self, _plug, _dataBlock): # Check if the plug is the output if (_plug == SculptNodeClass.m_outMesh): # Get data handles and typecast terrainDataHandle = _dataBlock.inputValue( SculptNodeClass.m_terrain) terrainValue = terrainDataHandle.asMesh() curveMaskDataHandle = _dataBlock.inputValue( SculptNodeClass.m_curveMask) curveMaskValue = curveMaskDataHandle.asNurbsCurve() sculptedMeshDataHandle = _dataBlock.inputValue( SculptNodeClass.m_sculptedMesh) sculptedMeshValue = sculptedMeshDataHandle.asMesh() sculptStrengthDataHandle = _dataBlock.inputValue( SculptNodeClass.m_sculptStrength) sculptStrengthValue = sculptStrengthDataHandle.asFloat() curveOffsetDataHandle = _dataBlock.inputValue( SculptNodeClass.m_curveOffset) curveOffsetValue = curveOffsetDataHandle.asFloat() maxProjectionDistanceDataHandle = _dataBlock.inputValue( SculptNodeClass.m_maxProjectionDistance) maxProjectionDistanceValue = maxProjectionDistanceDataHandle.asFloat( ) outMeshDataHandle = _dataBlock.outputValue( SculptNodeClass.m_outMesh) # Computation # Create a copy of the terrain meshDataFn = om.MFnMeshData() outTerrain = meshDataFn.create() outTerrainFn = om.MFnMesh() outTerrainFn.copy(terrainValue, outTerrain) # Get all the vertices from the terrain inTerrainFn = om.MFnMesh(terrainValue) vertexPositions = inTerrainFn.getPoints() # Create a function set for the curve and find the centre curveFn = om.MFnNurbsCurve(curveMaskValue) curveCentre = self.findCurveCentre(curveFn) # If this is the first computation, store the curve positions as the original and compute the affectedVertices if self.m_curveOriginalPoints == None: self.m_curveOriginalPoints = curveFn.cvPositions( om.MSpace.kWorld) # Create a polygon iterator polygonIterator = om.MItMeshPolygon(terrainValue) # Find the closest face on the terrain centreFaceIndex = inTerrainFn.getClosestPoint( curveCentre, om.MSpace.kWorld)[1] # Calculate the affected vertices self.findVerticesInsideCurve(polygonIterator, centreFaceIndex, curveFn, curveCentre, curveOffsetValue) # Store values self.m_lastCurveOffset = curveOffsetValue self.m_lastNumVertices = inTerrainFn.numVertices self.m_lastCurveCentreClosestVertex = centreFaceIndex # Check if the input terrain, curve offset or the curve has changed else: recomputeAffectedVertices = False centreFaceIndex = inTerrainFn.getClosestPoint( curveCentre, om.MSpace.kWorld)[1] if self.m_lastNumVertices != inTerrainFn.numVertices: recomputeAffectedVertices = True self.m_lastNumVertices = inTerrainFn.numVertices elif curveOffsetValue != self.m_lastCurveOffset: recomputeAffectedVertices = True self.m_lastCurveOffset = curveOffsetValue elif self.m_lastCurveCentreClosestVertex != centreFaceIndex: recomputeAffectedVertices = True self.m_lastCurveCentreClosestVertex = centreFaceIndex elif len(self.m_curveOriginalPoints) != curveFn.numCVs: recomputeAffectedVertices = True else: curvePoints = curveFn.cvPositions(om.MSpace.kWorld) for originalPos, newPos in zip(self.m_curveOriginalPoints, curvePoints): if originalPos != newPos: recomputeAffectedVertices = True break if recomputeAffectedVertices == True: # Create a polygon iterator polygonIterator = om.MItMeshPolygon(terrainValue) # Find the closest face on the terrain centreFaceIndex = inTerrainFn.getClosestPoint( curveCentre, om.MSpace.kWorld)[1] self.findVerticesInsideCurve(polygonIterator, centreFaceIndex, curveFn, curveCentre, curveOffsetValue) self.m_curveOriginalPoints == curveFn.cvPositions( om.MSpace.kWorld) # Create a function set for the sculpted mesh sculptedMeshFn = om.MFnMesh(sculptedMeshValue) accelerationParams = sculptedMeshFn.autoUniformGridParams() # Iterate through affected vertices and project onto the sculpted mesh numVertices = len(self.m_affectedVertices) for i in xrange(numVertices): # Find a ray intersection from the original point in the direction of the normal to the scul mesh raySource = om.MFloatPoint( vertexPositions[self.m_affectedVertices[i]]) normal = inTerrainFn.getVertexNormal( self.m_affectedVertices[i], True, om.MSpace.kWorld) intersection = sculptedMeshFn.closestIntersection( raySource, om.MFloatVector(normal), om.MSpace.kWorld, maxProjectionDistanceValue, True, accelParams=accelerationParams) # Calculate a vector from the original point to the new point difference = om.MPoint(intersection[0]) - vertexPositions[ self.m_affectedVertices[i]] # Ensure the vertices are not sliding perpendicular to the normal if difference * normal != 0.0: closestPointOnCurve = curveFn.closestPoint( vertexPositions[self.m_affectedVertices[i]], space=om.MSpace.kWorld)[0] vertexPositions[self.m_affectedVertices[ i]] += difference * sculptStrengthValue * self.calculateSoftSelectValue( curveCentre, vertexPositions[self.m_affectedVertices[i]], closestPointOnCurve) # Free the accelerator from memory as it is not automatically managed sculptedMeshFn.freeCachedIntersectionAccelerator() # Set the new vertices of the mesh outTerrainFn.setPoints(vertexPositions) # Set the output value outMeshDataHandle.setMObject(outTerrain) # Mark the plug as clean outMeshDataHandle.setClean()
def initialize(cls): print('initialize') nData = ompy.MFnNumericData() cData = ompy.MFnNurbsCurveData() mData = ompy.MFnMeshData() sData = ompy.MFnStringData() nAttr = ompy.MFnNumericAttribute() eAttr = ompy.MFnEnumAttribute() mAttr = ompy.MFnMatrixAttribute() gAttr = ompy.MFnGenericAttribute() tAttr = ompy.MFnTypedAttribute() sAttr = ompy.MFnTypedAttribute() cls.inAttrs = [] # OUT ATTR cls.inAttrs.append(mAttr.create('camMatrix', 'camMatrix', nData.kFloat)) drawPlaneMode_choices = ['none', 'foreground', 'background'] cls.inAttrs.append(eAttr.create('drawPlaneMode', 'drawPlaneMode', 0)) for i in range(0, len(drawPlaneMode_choices)): eAttr.addField(drawPlaneMode_choices[i], i) eAttr.channelBox = True cls.inAttrs.append(nAttr.create('shapes', 'shapes', nData.kInt, 0)) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append(nAttr.createPoint('coords', 'coords')) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append( nAttr.createPoint('screenSpaceOffsets', 'screenSpaceOffsets')) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append(nAttr.create('sizes', 'sizes', nData.kFloat, 1.0)) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append( nAttr.create('thicknesses', 'thicknesses', nData.kFloat, 1.0)) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append(nAttr.createPoint('colors', 'colors')) nAttr.array = True #nAttr.dynamic = True nAttr.usesArrayDataBuilder = True cls.inAttrs.append(tAttr.create('names', 'names', sData.kString)) tAttr.array = True #nAttr.dynamic = True tAttr.usesArrayDataBuilder = True ''' cls.attrOutTrig = nAttr.create( 'outTrig', 'outTrig' , nData.kFloat ) nAttr.setReadable(True) nAttr.setStorable(True) nAttr.setConnectable(True) ''' for i in range(0, len(cls.inAttrs)): cls.addAttribute(cls.inAttrs[i]) #INFLUENCE '''