# Manipulating Data in 3D

Knobs in 3D are largely the same as knobs in 2D, which you can find details of here: Knobs, Control Panels and In-Viewer Controls. However, there are some extra considerations when writing a 3D knob:

- it needs to check whether the Viewer is in 3D mode before drawing itself

- it may need to draw the handle differently, or not at all, depending on the current render pass

## Checking for 3D Mode

You can easily check whether the Viewer is in 3D mode through the ViewerContext:

    void draw_handles(DD::Image::ViewerContext* ctx) {
      if (ctx->viewer_mode() != VIEWER_2D) {
        // draw the handle.
      }
    }

## Check the Render Pass

NUKE’s 3D Viewer does a series of rendering passes to draw the final image, so your handle drawing code may be invoked up to three times:

- once for the solid object pass

- once for the wireframe pass

- once for the hidden lines pass

You can tell what the current render pass is by checking the result of `ViewerContext::event()`:

Event | Current Render Pass
--- | ---
DRAW_OPAQUE | Drawing solid objects. If your handle should appear to be part of the scene, just like regular geometry, this is when you should draw it.
DRAW_LINES | Wireframe pass. This is where most handles are drawn.
DRAW_STIPPLED | Hidden line pass. In this pass, we’re drawing lines which would normally be hidden behind geometry. The line style is changed to stippled and the OpenGL depth test function is inverted. Draw here if you want parts of your handle that would otherwise be obscured to show up.

There are other values that `event()` can return besides those above; you should make sure you aren’t drawing for any of those.

For example:

    void draw_handles(DD::Image::ViewerContext* ctx) {
      if (ctx->viewer_mode() == VIEWER_2D)
        return;

      if (ctx->event() == DRAW_LINES || ctx->event() == DRAW_STIPPLED) {
        // draw the handle.
      }
    }