I was making these couple of doodles and some ideas that were helpful for making this were:
1. staying loose on the initial outline. I found it fun to lower the opacity and redraw another time than to think too much about getting outlines on first try.
2. staying loose on the initial greying of background. Again I really enjoyed trying out different ideas and not really thinking too much about how they would look but more about enjoying drawing the strokes and planes etc.
Also, here are some rough sketches and ideas at a python node plugin I wrote to hold some scene data I may have made some mistakes in my explanations and there may be some bugs in the code.
Hope it is helpful.
#for some error checking
import sys
#get necessary api functions
import maya.OpenMaya as OpenMaya
#need this because were making a node
import maya.OpenMayaMPx as OpenMayaMPx
kPluginNodeTypeName = "camNode"
#using a temporary id
camNodeId = OpenMaya.MTypeId(0x0000)
#build our node off of Maya's our constructor needs to call parent class
class camNode(OpenMayaMPx.MPxNode):
#in c these are protected, they are the attribute names
transform = OpenMaya.MObject()
startFrame = OpenMaya.MObject()
endFrame = OpenMaya.MObject()
output = OpenMaya.MObject()
def __init__(self):
OpenMayaMPx.MPxNode.__init__(self)
##use inputs of node to generate output
#@note in c explicitly give it the type for input parameters, in python types are ommited
#@param plug tells us the attributes that need to be recomputed
#@param use dataBlock to find all nodes attributes can use
##
def compute(self,plug,dataBlock):
#in c would have ommited the class part
if( plug == camNode.startFrame ):
print 'Great An Update in -- startFrame'
#in c what is returned from block.inputValue(...) is a reference ex a MFloatVector&
#in python forgetting about the type that is returned
sframeHandle = dataBlock.inputValue(camNode.startFrame)
startFloat = frameHandle.asFloat()
print 'Start Frame is >>%d' %startFloat
#mark plug as clean
dataBlock.setClean(plug)
if( plug == camNode.endFrame ):
print 'Great An Update in -- endFrame'
eframeHandle = dataBlock.inputValue(camNode.endFrame)
endFloat = eframeHandle.asFloat()
print 'End Frame is >>%d' %endFloat
dataBlock.setClean(plug)
if( plug == camNode.transform ):
print 'Great An Update in -- transform'
tfHandle = dataBlock.inputValue(camNode.transform)
tfFloat = tfHandle.asFloat()
print 'Transform is >>%d' %tfFloat
dataBlock.setClean(plug)
if( plug == camNode.output ):
print 'Great an Update in Ouput'
#in c would have passed output and maybe an error checking object
outHandle = dataBlock.outputValue( camNode.output )
#mark output value as clean
#in c i think would have used the handle to setClean not the dataBlock
dataBlock.setClean(plug)
##allow Maya to instantiate an instance of our custom node, its called every time a new instance
#of node is made ex: with Maya's createNode command
#@note in c this is creator()
##
def nodeCreator():
return OpenMayaMPx.asMPxPtr( camNode() )
##create the node attributes and set their types, keyable status ets
#this is called once when Maya loads the plugin ex: pressing load in plugin manager
#@note in c this is initialize()
##
def nodeInitializer():
#"""
#similar in c, this is needed to create numeric attributes for our node
#startFrame
nAttr = OpenMaya.MFnNumericAttribute();
#This part actually creates the attribute, in c the create would also take a status object
#also in c would have set default value separately using setDefault(...)
camNode.startFrame = nAttr.create( "startFrame","sf", OpenMaya.MFnNumericData.kFloat, 0.0)
#so when file is saved the attribute is written out
nAttr.setStorable(1)
#so setAttr commands can change this attribute, and attribute can be a connection destination
nAttr.setWritable(1)
#so cannot be keyframed
nAttr.setKeyable(0)
#endFrame
nAttr = OpenMaya.MFnNumericAttribute();
camNode.endFrame = nAttr.create( "endFrame","ef", OpenMaya.MFnNumericData.kFloat, 0.0)
nAttr.setStorable(1)
nAttr.setWritable(1)
nAttr.setKeyable(0)
#transform
nAttr = OpenMaya.MFnNumericAttribute();
camNode.transform = nAttr.create( "camTransform","ct", OpenMaya.MFnNumericData.kFloat, 0.0)
nAttr.setStorable(1)
nAttr.setWritable(1)
nAttr.setKeyable(0)
#output
nAttr = OpenMaya.MFnNumericAttribute();
camNode.output = nAttr.create( "output","out", OpenMaya.MFnNumericData.kFloat, 0.0)
nAttr.setStorable(1)
nAttr.setWritable(1)
nAttr.setKeyable(0)
#now we add the attributes to the node, in c I think would ommit the camNode
camNode.addAttribute(camNode.startFrame)
camNode.addAttribute(camNode.endFrame)
camNode.addAttribute(camNode.transform)
camNode.addAttribute(camNode.output)
#if needed startFrame to affect output attribute would add
#camNode.attributeAffects( camNode.startFrame, camNode.output )
#camNode.attributeAffects( camNode.endFrame, camNode.output )
#camNode.attributeAffects( camNode.transform, camNode.output )
#"""
##so when plug in loaded Maya can register the node
#
##
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
#in c i think would explicitly tell register node where to find creator, initialize, and id
mplugin.registerNode( kPluginNodeTypeName, camNodeId, nodeCreator, nodeInitializer)
except:
sys.stderr.write("Failed register node: %s" %kPluginNodeTypeName)
raise
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
#only need the id to deregister node
mplugin.deregisterNode(camNodeId)
except:
sys.stderr.write("Failed deregister node: %s" %kPluginNodeTypeName)
raise
Inspired by Maya included tutorial documentation on API especially lambertShader.cpp and sineNode.py (autodesk dot com).
Cheers,
Nate



