Created
May 10, 2013 06:13
-
-
Save hmasato/5552695 to your computer and use it in GitHub Desktop.
[MAYA] cfField_min.py (curveFlow Field)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #-------------------------------- | |
| # cfField.py: curveFlow Field | |
| #-------------------------------- | |
| import math, sys | |
| import maya.OpenMaya as om | |
| import maya.OpenMayaUI as omUI | |
| import maya.OpenMayaMPx as omMPx | |
| import maya.OpenMayaRender as omRen | |
| kPlgName = "cfField" | |
| kPlgID = om.MTypeId(0x87102) | |
| glFT = omRen.MHardwareRenderer.theRenderer().glFunctionTable() | |
| def statusError(msg): | |
| sys.stderr.write("%s\n" % msg) | |
| raise | |
| class cfField(omMPx.MPxFieldNode): | |
| aConstDistance = om.MObject() | |
| aAttractRatioIn = om.MObject() | |
| aAttractRatioOut = om.MObject() | |
| aSectionRatioIn = om.MObject() | |
| aSectionRatioOut = om.MObject() | |
| aTangentRatioIn = om.MObject() | |
| aTangentRatioOut = om.MObject() | |
| aInputCurve = om.MObject() | |
| def __init__(self): | |
| omMPx.MPxFieldNode.__init__(self) | |
| def compute(self, plg, blk): | |
| oForce = omMPx.cvar.MPxFieldNode_mOutputForce | |
| if not (plg == oForce): return | |
| mIdx = plg.logicalIndex() | |
| hInArr = blk.outputArrayValue(omMPx.cvar.MPxFieldNode_mInputData) | |
| hInArr.jumpToElement(mIdx) | |
| hCmpd = hInArr.inputValue() | |
| dP = hCmpd.child(omMPx.cvar.MPxFieldNode_mInputPositions).data() | |
| pnts = om.MFnVectorArrayData(dP).array() | |
| dV = hCmpd.child(omMPx.cvar.MPxFieldNode_mInputVelocities).data() | |
| vels = om.MFnVectorArrayData(dV).array() | |
| dM = hCmpd.child(omMPx.cvar.MPxFieldNode_mInputMass).data() | |
| masses = om.MFnDoubleArrayData(dM).array() | |
| f = om.MVectorArray() | |
| self.__applyCurveFlow(blk, pnts, vels, masses, f) | |
| hOut = blk.outputArrayValue(oForce).builder().addElement(mIdx) | |
| hOut.setMObject(om.MFnVectorArrayData().create(f)) | |
| blk.setClean(plg) | |
| #------------------------------------------------------------------ | |
| def __applyCurveFlow(self, blk, pnts, vels, masses, oForce): | |
| if pnts.length() != vels.length(): return | |
| mag = self.__magnitude(blk) | |
| if -0.0001 < mag and mag < 0.0001: return | |
| constDist = self.__constDistance(blk) | |
| minDist = 0.0 | |
| maxDist = constDist | |
| useMaxDist = self.__useMaxDistance(blk) | |
| if useMaxDist: | |
| minDist = constDist | |
| maxDist = self.__maxDistance(blk) | |
| constDist = maxDist - minDist | |
| if maxDist < 0.0001: return | |
| oForce.clear() | |
| atten = self.__attenuation(blk) | |
| fAttIn = self.__attractRatioIn(blk) | |
| fAttOut = self.__attractRatioOut(blk) | |
| fSectIn = self.__sectionRatioIn(blk) | |
| fSectOut = self.__sectionRatioOut(blk) | |
| fTanIn = self.__tangentRatioIn(blk) | |
| fTanOut = self.__tangentRatioOut(blk) | |
| pos = self.__ownerPos(blk) | |
| crv = self.__inputCurve(blk) | |
| if crv.isNull(): return | |
| try: crvFn = om.MFnNurbsCurve(crv) | |
| except: return | |
| utl = om.MScriptUtil() | |
| pk = om.MScriptUtil().asDoublePtr() | |
| pks = om.MScriptUtil().asDoublePtr() | |
| pke = om.MScriptUtil().asDoublePtr() | |
| crvFn.getKnotDomain(pks, pke) | |
| ks=utl.getDouble(pks) | |
| ke=utl.getDouble(pke) | |
| npnts = pnts.length() | |
| for i in range(npnts): | |
| f = om.MVector(0,0,0) | |
| fallOff = 1.0 | |
| v = vels[i] | |
| fv = v.length() | |
| if fv < 0.0001: #----------------- | |
| oForce.append(f) | |
| continue | |
| p = om.MPoint(pnts[i]) | |
| cp = crvFn.closestPoint(p, pk, 0.1, om.MSpace.kWorld) | |
| dp = p-cp | |
| fdp = dp.length() | |
| if maxDist < fdp: #----------------- | |
| oForce.append(f) | |
| continue | |
| k = utl.getDouble(pk) | |
| if k <= ks or ke <= k: #----------------- | |
| oForce.append(f) | |
| continue | |
| # u = (k-ks) / (ke-ks) | |
| # n = crvFn.normal(k, om.MSpace.kObject) | |
| t = crvFn.tangent(k, om.MSpace.kWorld) | |
| vt = t * (t * v) | |
| vn = v - vt | |
| vt = vt.normal() * fv #--------force keep length | |
| vn = vn.normal() * fv #--------force keep length | |
| va = -dp.normal() * fv #--------force keep length | |
| dist = 0.0 | |
| if fdp > minDist: dist=(fdp-minDist)/constDist | |
| if useMaxDist: fallOff = self.falloffCurve(dist) | |
| Dn = fSectIn * (1.0-dist) + fSectOut * dist | |
| Dt = fTanIn * (1.0-dist) + fTanOut * dist | |
| Da = fAttIn * (1.0-dist) + fAttOut * dist | |
| # f = (vn * Dn + vt * Dt + va * Da - v ) * mag * fallOff | |
| f = (vn * Dn + vt * Dt + va * Da) * mag * fallOff | |
| oForce.append(f) | |
| #------------------------------------------------------------------ | |
| def draw (self, view, path, style, status): | |
| TORUS_2PI = 2.0 * 3.14159265 | |
| EDGES = 8 | |
| SEGMENTS = 8 | |
| view.beginGL() | |
| for j in range(SEGMENTS): | |
| glFT.glPushMatrix() | |
| glFT.glRotatef(360.0 * j / SEGMENTS, 0.0, 1.0, 0.0) | |
| glFT.glTranslatef(1.5, 0.0, 0.0) | |
| for i in range(EDGES): | |
| glFT.glBegin(omRen.MGL_LINE_STRIP) | |
| p0 = TORUS_2PI * i / EDGES | |
| p1 = TORUS_2PI * (i+1) / EDGES | |
| glFT.glVertex2f(math.cos(p0), math.sin(p0)) | |
| glFT.glVertex2f(math.cos(p1), math.sin(p1)) | |
| glFT.glEnd() | |
| glFT.glPopMatrix() | |
| view.endGL() | |
| def getForceAtPoint(self, pnts, vels, masses, oForce, dtime): | |
| blk = forceCache() | |
| self.__applyCurveFlow(blk, pnts, vels, masses, oForce) | |
| def __ownerPos(self, blk): | |
| oP = om.MVectorArray() | |
| if self.__applyPerVertex(blk): | |
| try: hOP = blk.inputValue(omMPx.cvar.MPxFieldNode_mOwnerPosData) | |
| except: oP.append(self.__getWPos()) | |
| else: | |
| fnOP = om.MFnVectorArrayData(hOP.data()) | |
| try: posArray = fnOP.array() | |
| except: oP.append(self.__getWPos()) | |
| else: | |
| for i in range(posArray.length()): oP.append(posArray[i]) | |
| else: | |
| try: oC = self.__ownerCentroid(blk) | |
| except: oP.append(self.__getWPos()) | |
| else: | |
| oP.append(oC) | |
| return oP | |
| def __getWPos(self): | |
| node = self.thisMObject() | |
| fn = om.MFnDependencyNode(node) | |
| wMtxAttr = fn.attribute("worldMatrix") | |
| mtxplg = om.MPlug(node, wMtxAttr).elementByLogicalIndex(0) | |
| mtxObj = mtxplg.asMObject(mtxObj) | |
| wmtx = om.MFnMatrixData(mtxObj).matrix() | |
| return om.MVector(wmtx(3, 0), wmtx(3, 1), wmtx(3, 2)) | |
| def __magnitude(self, blk): | |
| return blk.inputValue(omMPx.cvar.MPxFieldNode_mMagnitude).asDouble() | |
| def __attenuation(self, blk): | |
| return blk.inputValue(omMPx.cvar.MPxFieldNode_mAttenuation).asDouble() | |
| def __maxDistance(self, blk): | |
| return blk.inputValue(omMPx.cvar.MPxFieldNode_mMaxDistance).asDouble() | |
| def __useMaxDistance(self, blk): | |
| return blk.inputValue(omMPx.cvar.MPxFieldNode_mUseMaxDistance).asBool() | |
| def __applyPerVertex(self, blk): | |
| return blk.inputValue(omMPx.cvar.MPxFieldNode_mApplyPerVertex).asBool() | |
| def __constDistance(self, blk): | |
| return blk.inputValue(cfField.aConstDistance).asDouble() | |
| def __attractRatioIn(self, blk): | |
| return blk.inputValue(cfField.aAttractRatioIn).asDouble() | |
| def __attractRatioOut(self, blk): | |
| return blk.inputValue(cfField.aAttractRatioOut).asDouble() | |
| def __sectionRatioIn(self, blk): | |
| return blk.inputValue(cfField.aSectionRatioIn).asDouble() | |
| def __sectionRatioOut(self, blk): | |
| return blk.inputValue(cfField.aSectionRatioOut).asDouble() | |
| def __tangentRatioIn(self, blk): | |
| return blk.inputValue(cfField.aTangentRatioIn).asDouble() | |
| def __tangentRatioOut(self, blk): | |
| return blk.inputValue(cfField.aTangentRatioOut).asDouble() | |
| def __inputCurve(self, blk): | |
| try: | |
| return blk.inputValue(cfField.aInputCurve).asNurbsCurve() | |
| # return blk.inputValue(cfField.aInputCurve).asNurbsCurveTransformed() | |
| except: | |
| return om.MObject().kNullObj; | |
| def __ownerCentroid(self, blk): | |
| hX = blk.inputValue(omMPx.cvar.MPxFieldNode_mOwnerCentroidX) | |
| hY = blk.inputValue(omMPx.cvar.MPxFieldNode_mOwnerCentroidY) | |
| hZ = blk.inputValue(omMPx.cvar.MPxFieldNode_mOwnerCentroidZ) | |
| return om.MVector(hX.asDouble(), hY.asDouble(), hZ.asDouble()) | |
| def nodeCreator(): | |
| return omMPx.asMPxPtr(cfField()) | |
| def nodeInitializer(): | |
| nTyp=om.MFnNumericData | |
| numAttr = om.MFnNumericAttribute() | |
| cfField.aConstDistance = numAttr.create("constDistance", "ctd", nTyp.kDouble, 10.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aConstDistance) | |
| cfField.aAttractRatioIn = numAttr.create("attractRatioIn", "ati", nTyp.kDouble, 0.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aAttractRatioIn) | |
| cfField.aAttractRatioOut = numAttr.create("attractRatioOut", "ato", nTyp.kDouble, 0.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aAttractRatioOut) | |
| cfField.aSectionRatioIn = numAttr.create("sectionRatioIn", "sci", nTyp.kDouble, 0.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aSectionRatioIn) | |
| cfField.aSectionRatioOut = numAttr.create("sectionRatioOut", "sco", nTyp.kDouble, -1.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aSectionRatioOut) | |
| cfField.aTangentRatioIn = numAttr.create("tangentRatioIn", "tgi", nTyp.kDouble, 0.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aTangentRatioIn) | |
| cfField.aTangentRatioOut = numAttr.create("tangentRatioOut", "tgo", nTyp.kDouble, 0.0) | |
| numAttr.setKeyable(True) | |
| cfField.addAttribute(cfField.aTangentRatioOut) | |
| typAttr = om.MFnTypedAttribute() | |
| cfField.aInputCurve = typAttr.create('inputCurve', 'icv', om.MFnData.kNurbsCurve) | |
| typAttr.setStorable(True) | |
| cfField.addAttribute(cfField.aInputCurve) | |
| cfField.attributeAffects(cfField.aInputCurve, omMPx.cvar.MPxFieldNode_mOutputForce) | |
| def initializePlugin(mobj): | |
| mplg = omMPx.MFnPlugin(mobj, "Autodesk", "1.0", "Any") | |
| try: mplg.registerNode(kPlgName, kPlgID, nodeCreator, nodeInitializer, omMPx.MPxNode.kFieldNode) | |
| except: statusError("Failed to register node: %s" % kPlgName) | |
| def uninitializePlugin(mobj): | |
| mplg = omMPx.MFnPlugin(mobj) | |
| try: mplg.deregisterNode(kPlgID) | |
| except: statusError("Failed to deregister node: %s" % kPlgName) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment