贝塞尔(Bezier)曲线节点

ぐ巨炮叔叔 提交于 2020-03-17 07:36:52

在网上看到一个bezier曲线的公式,那就用Maya的节点来实现下,看看效果,具体公式如下图:
在这里插入图片描述
这个是二维的,三维的化再加个z轴向就行,


import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMaya as OpenMaya


class BezierCubic(OpenMayaMPx.MPxNode):
    kPluginNodeId = OpenMaya.MTypeId(0x00000121)

    aP1 = OpenMaya.MObject()
    aP2 = OpenMaya.MObject()
    aP3 = OpenMaya.MObject()
    aP4 = OpenMaya.MObject()

    aSum = OpenMaya.MObject()
    aBias = OpenMaya.MObject()

    def __init__(self):
        OpenMayaMPx.MPxNode.__init__(self)

    def compute(self, plug, data):

        p1 = data.inputValue(BezierCubic.aP1).asVector()
        p2 = data.inputValue(BezierCubic.aP2).asVector()
        p3 = data.inputValue(BezierCubic.aP3).asVector()
        p4 = data.inputValue(BezierCubic.aP4).asVector()
        t = data.inputValue(BezierCubic.aBias).asFloat()

        sum = p1 * pow(1 - t, 3) + p2 * 3 * t * pow(1 - t, 2) + p3 * 3 * pow(t, 2) * (1 - t) + p4 * pow(t, 3)

        outputData = data.outputValue(BezierCubic.aSum)
        outputData.set3Double(sum[0], sum[1], sum[2])

        data.setClean(plug)


def creator():
    return OpenMayaMPx.asMPxPtr(BezierCubic())


def initialize():
    nAttr = OpenMaya.MFnNumericAttribute()

    BezierCubic.aP1 = nAttr.create('Point1', 'p1', OpenMaya.MFnNumericData.k3Double)
    BezierCubic.addAttribute(BezierCubic.aP1)

    BezierCubic.aP2 = nAttr.create('Point2', 'p2', OpenMaya.MFnNumericData.k3Double)
    BezierCubic.addAttribute(BezierCubic.aP2)

    BezierCubic.aP3 = nAttr.create('Point3', 'p3', OpenMaya.MFnNumericData.k3Double)
    BezierCubic.addAttribute(BezierCubic.aP3)

    BezierCubic.aP4 = nAttr.create('Point4', 'p4', OpenMaya.MFnNumericData.k3Double)
    BezierCubic.addAttribute(BezierCubic.aP4)

    BezierCubic.aSum = nAttr.create('SumBezier', 'sum', OpenMaya.MFnNumericData.k3Double)
    nAttr.setWritable(True)
    BezierCubic.addAttribute(BezierCubic.aSum)

    BezierCubic.aBias = nAttr.create('Bias', 't', OpenMaya.MFnNumericData.kFloat, 0.0)
    nAttr.setSoftMin = 0.0
    nAttr.setSoftMax = 1.0
    nAttr.setKeyable(True)
    nAttr.setWritable(True)
    BezierCubic.addAttribute(BezierCubic.aBias)

    BezierCubic.attributeAffects(BezierCubic.aBias, BezierCubic.aSum)
    BezierCubic.attributeAffects(BezierCubic.aP1, BezierCubic.aSum)
    BezierCubic.attributeAffects(BezierCubic.aP2, BezierCubic.aSum)
    BezierCubic.attributeAffects(BezierCubic.aP3, BezierCubic.aSum)
    BezierCubic.attributeAffects(BezierCubic.aP4, BezierCubic.aSum)


def initializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj, 'Chuck', '1.0', 'Bezier')
    try:
        plugin.registerNode('BezierCubic', BezierCubic.kPluginNodeId, creator, initialize)

    except:
        raise RuntimeError('Failed to register node')


def uninitializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj)
    try:
        plugin.deregisterNode(BezierCubic.kPluginNodeId)

    except:
        raise RuntimeError('Failed to unregister node')

核心的代码就这一句
sum = p1 * pow(1 - t, 3) + p2 * 3 * t * pow(1 - t, 2) + p3 * 3 * pow(t, 2) * (1 - t) + p4 * pow(t, 3)
t为小球在Bezier曲线上的位置,这里设置为1到0,也就是从起始位置到结束位置。

在Maya里挂载下就可以执行我们的操作了

import maya.cmds as cmds

from math import *

l1 = cmds.spaceLocator(n='loc1')
cmds.xform(l1, t=(-6, 0, -2), ws=1)

l2 = cmds.spaceLocator(n='loc2')
cmds.xform(l2, t=(-5, 0, -6), ws=1)

l3 = cmds.spaceLocator(n='loc3')
cmds.xform(l3, t=(1, 0, -6), ws=1)

l4 = cmds.spaceLocator(n='loc4')
cmds.xform(l4, t=(2, 0, -2), ws=1)

for i in range(0, 11):
    node_name = 'BezierCubic' + str(i)
    sphere_name = 'sphere' + str(i)
    sphere = cmds.sphere(n=sphere_name, r=.5)
    cmds.createNode('BezierCubic', n=node_name)
    cmds.connectAttr('loc1.translate', node_name + '.Point1')
    cmds.connectAttr('loc2.translate', node_name + '.Point2')
    cmds.connectAttr('loc3.translate', node_name + '.Point3')
    cmds.connectAttr('loc4.translate', node_name + '.Point4')
    cmds.connectAttr(node_name + '.SumBezier', sphere_name + '.translate')
    cmds.setAttr(node_name + '.Bias', i / 1.0 * 0.1)

这是最后的实际效果

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!