Drawing and refresh

Drawing is a two step process. In the first, the geometry and materials are evaluated and all of the information necessary for drawing is placed onto a queue. In the second, the actual OpenGL drawing occurs. This two step process allows your shapes to take advantage of the multi-threaded drawing capabilities of Maya.

Drawing occurs whenever the camera changes or the view has to be refreshed. When this happens, the MPxSurfaceShapeUI::getDrawRequest function is called. This is Maya’s way of asking the shape what it needs to draw. Inside this function you should query the drawing state, using MDrawInfo, and then construct a draw request (MDrawRequest) to place on the queue. You will often want to place multiple requests on the queue (MDrawRequestQueue) in this function. For instance, in shaded mode if your shape is selected you may want to add a request to draw the shaded object and another request to draw wireframe on top of the shaded object.

The draw data (MDrawData) holds information specific to your shape which Maya does not intrinsically know about. The draw data acts as a container to pass your geometry through the draw request queue. For each draw request you must create and add a draw data object which contains geometry-specific information that you will need in the subsequent call to MPxSurfaceShapeUI::draw.

To create draw data, use the function MPxSurfaceShapeUI::getDrawData and to add the data to a request use MDrawRequest::setDrawData. The following example shows how to create a draw request and draw data for your geometry.

void yourShapeUI::getDrawRequests( const MDrawInfo & info,
 bool objectAndActiveOnly,
 MDrawRequestQueue & queue )
{
    MDrawData data;
    MDrawRequest request = info.getPrototype( *this );
    yourShape* shapeNode = (yourShape*)surfaceShape();
    yourGeom* geom = shapeNode->geometry();
    getDrawData( geom, data );
    request.setDrawData( data );
    ...
}

The draw request (MDrawRequest) should be created in the overridden MPxSurfaceShapeUI::getDrawRequests method. Once the request is created the appropriate "set" methods of this class should be used to define what is being requested. Then the request should be placed on the draw request queue using MDrawRequestQueue::add.

The draw token is an integer value which you can use to specify what is to be drawn. This is object specific and so you should define an enum with the information you require to decide what is being drawn in your MPxSurfaceShapeUI::draw method. Here is an example of a draw token for a mesh object:

 enum {
          kDrawVertices, // component token
          kDrawWireframe,
          kDrawWireframeOnShaded,
          kDrawSmoothShaded,
          kDrawFlatShaded,
          kLastToken
      };

Maya processes the draw request queue and for each draw request, calls the corresponding objects draw function. In the case of user defined shapes, your MPxSurfaceShapeUI::draw method is called.

Drawing in shaded mode

Supporting shaded mode display is a two step process. The first step occurs in your getDrawRequests function. Here you must "evaluate" or setup the material so that it can be displayed when your object is drawn. The second step occurs in your draw function where you must setup the view to display the material.

The following code demonstrates how to setup the material in your getDrawRequests function if the request is for shaded mode display.

 MDagPath path = info.multiPath();
 M3dView view = info.view();
 MMaterial material = MPxSurfaceShapeUI::material( path );
 material.evaluateMaterial( view, path );
 if ( material.materialIsTextured() ) {
     material.evaluateTexture( data );
 }
 request.setMaterial( material );

In your draw function you will need to setup the scene view so that it can display the material. This is done using MMaterial::setMaterial. To set up the scene view to display textures, use MMaterial::applyTexture. The following code demonstrates this.

void yourShapeUI::draw( const MDrawRequest& request,
 M3dView & view ) const
{
     ...
     MMaterial material = request.material();
     material.setMaterial( request.isTransparent() );
     drawTexture = material.materialIsTextured();
     if ( drawTexture ) glEnable(GL_TEXTURE_2D);
     if ( drawTexture ) {
         material.applyTexture( view, data );
     }
     ...
}
NOTE:

All OpenGL calls should be enclosed by calls to M3dView::beginGL() and M3dView::endGL().