scripted/pyVertexBufferMutator.py

scripted/pyVertexBufferMutator.py
1 # Copyright 2015 Autodesk, Inc. All rights reserved.
2 #
3 # Use of this software is subject to the terms of the Autodesk
4 # license agreement provided at the time of installation or download,
5 # or which otherwise accompanies this software in either electronic
6 # or hard copy form.
7 
8 from ctypes import *
9 import maya.api.OpenMayaRender as omr
10 import maya.api.OpenMaya as om
11 
12 # Example plugin: vertexBufferMutator.cpp
13 #
14 # This plug-in is an example of a custom MPxVertexBufferMutator.
15 # It provides custom vertex streams based on shader requirements coming from
16 # an MPxShaderOverride. The semanticName() in the MVertexBufferDescriptor is used
17 # to signify a unique identifier for a custom stream.
18 
19 # This plugin is meant to be used in conjunction with the hwPhongShader
20 # where the position geometry is defined with the semantic "swizzlePosition"
21 
22 def maya_useNewAPI():
23  """
24  The presence of this function tells Maya that the plugin produces, and
25  expects to be passed, objects created using the Maya Python API 2.0.
26  """
27  pass
28 
29 class MyCustomBufferMutator(omr.MPxVertexBufferMutator):
30  def __init__(self):
31  omr.MPxVertexBufferMutator.__init__(self)
32 
33  def modifyVertexStream(self, object, vertexBuffer, targetIndexing):
34  # get the descriptor from the vertex buffer.
35  # It describes the format and layout of the stream.
36  descriptor = vertexBuffer.descriptor()
37 
38  # we are expecting a float stream.
39  if descriptor.dataType != omr.MGeometry.kFloat:
40  return
41 
42  # we are expecting a float3
43  if descriptor.dimension != 3:
44  return
45 
46  # we are expecting a position channel
47  if descriptor.semantic != omr.MGeometry.kPosition:
48  return
49 
50  # get the mesh from the current path
51  # if it is not a mesh we do nothing.
52  mesh = om.MFnMesh(object)
53 
54  vertexCount = vertexBuffer.vertexCount()
55  if vertexCount <= 0:
56  return
57 
58  # acquire the buffer to fill with data.
59  buffer = vertexBuffer.acquire(vertexCount, False) # writeOnly = False : we want the current buffer values
60 
61  inc = sizeof(c_float)
62  address = buffer
63 
64  for i in range(0, vertexCount):
65  # Here we swap the x, y and z values
66  xaddr = address
67  yaddr = address+inc
68  zaddr = address+2*inc
69  address += 3*inc
70 
71  x = c_float.from_address(xaddr).value
72  c_float.from_address(xaddr).value = c_float.from_address(yaddr).value # y --> x
73  c_float.from_address(yaddr).value = c_float.from_address(zaddr).value # z --> y
74  c_float.from_address(zaddr).value = x # x --> z
75 
76  # commit the buffer to signal completion.
77  vertexBuffer.commit(buffer)
78 
79 # This is the buffer generator creation function registered with the DrawRegistry.
80 # Used to initialize the generator.
81 def createMyCustomBufferMutator():
82  return MyCustomBufferMutator()
83 
84 # The following routines are used to register/unregister
85 # the vertex mutators with Maya
86 def initializePlugin(obj):
87 
88  omr.MDrawRegistry.registerVertexBufferMutator("swizzlePosition", createMyCustomBufferMutator)
89 
90 def uninitializePlugin(obj):
91 
92  omr.MDrawRegistry.deregisterVertexBufferMutator("swizzlePosition")
93