1

I created an MPxLocatorNode with Maya api in c++. The node doesn't have a compute method, it just has different styles of shapes that is drawn with open gl in the draw method.

One style it draws is the cross, exactly the same as a locator. So I went to take some benchmarks to compare it to a native locator and noticed that my node's performance is way slower. Maya's locator was roughly 4x faster!

1000 nodes

My node: 74 fps

Maya's locator: 300 fps

What am I doing wrong that's slowing down the performance of my node? The only thing I can think of is that I am getting my node's MObjects via MPlug in the draw method, unlike getting them from a data block like you could in the compute method.

My cpp file is below. Most of the slow down should be in the draw method.

#include "point.h"

MTypeId Point::id(0x00000900);

MObject Point::input_display;
MObject Point::input_box;
MObject Point::input_cross;
MObject Point::input_tick;
MObject Point::input_axis;
MObject Point::input_color;

MColorArray Point::colors;


Point::Point() {
}

void Point::postConstructor() {
    MObject self = thisMObject();
    MFnDependencyNode fn_node(self);
    fn_node.setName("pointShape#");
}

Point::~Point() {
}

void* Point::creator() {
    return new Point();
}

MStatus Point::initialize() {
    MFnNumericAttribute nAttr;

    input_display = nAttr.create("display", "display", MFnNumericData::kInt, 1);
    nAttr.setKeyable(true);
    nAttr.setMin(0);
    nAttr.setMax(1);
    addAttribute(input_display);

    input_box = nAttr.create("box", "box", MFnNumericData::kInt, 0);
    nAttr.setKeyable(true);
    nAttr.setMin(0);
    nAttr.setMax(1);
    addAttribute(input_box);

    input_cross = nAttr.create("cross", "cross", MFnNumericData::kInt, 1);
    nAttr.setKeyable(true);
    nAttr.setMin(0);
    nAttr.setMax(1);
    addAttribute(input_cross);

    input_tick = nAttr.create("tick", "tick", MFnNumericData::kInt, 0);
    nAttr.setKeyable(true);
    nAttr.setMin(0);
    nAttr.setMax(1);
    addAttribute(input_tick);

    input_axis = nAttr.create("axis", "axis", MFnNumericData::kInt, 0);
    nAttr.setKeyable(true);
    nAttr.setMin(0);
    nAttr.setMax(1);
    addAttribute(input_axis);

    MFnEnumAttribute eAttr;

    input_color = eAttr.create("color", "color", MFnData::kNumeric);

    eAttr.addField("Black", 0);
    eAttr.addField("Grey", 1);
    eAttr.addField("White", 2);
    eAttr.addField("Red", 3);
    eAttr.addField("Light red", 4);
    eAttr.addField("Dark red", 5);
    eAttr.addField("Green", 6);
    eAttr.addField("Light green", 7);
    eAttr.addField("Dark green", 8);
    eAttr.addField("Blue", 9);
    eAttr.addField("Light blue", 10);
    eAttr.addField("Dark blue", 11);
    eAttr.addField("Purple", 12);
    eAttr.addField("Magenta", 13);
    eAttr.addField("Brown", 14);
    eAttr.addField("Yellow", 15);
    eAttr.addField("Dark yellow", 16);
    eAttr.addField("Orange", 17);

    eAttr.setDefault(8);
    eAttr.setKeyable(true);
    eAttr.setStorable(true);
    addAttribute(input_color);

    colors.append(MColor(0.0f, 0.0f, 0.0f)); // black
    colors.append(MColor(0.5f, 0.5f, 0.5f)); // grey
    colors.append(MColor(1.0f, 1.0f, 1.0f)); // white
    colors.append(MColor(1.0f, 0.0f, 0.0f)); // red
    colors.append(MColor(1.0f, 0.6899999976158142f, 0.6899999976158142f)); // light_red
    colors.append(MColor(0.5f, 0.0f, 0.0f)); // dark_red
    colors.append(MColor(0.0f, 1.0f, 0.0f)); // green
    colors.append(MColor(0.5f, 1.0f, 0.5f)); // light_green
    colors.append(MColor(0.0f, 0.25f, 0.0f)); // dark_green
    colors.append(MColor(0.1889999955892563f, 0.6299999952316284f, 0.6299999952316284f)); // blue
    colors.append(MColor(0.3919999897480011f, 0.8629999756813049f, 1.0f)); // light_blue
    colors.append(MColor(0.0f, 0.01600000075995922f, 0.37599998712539673f)); // dark_blue
    colors.append(MColor(0.25f, 0.0f, 0.25f)); // purple
    colors.append(MColor(1.0f, 0.0f, 1.0f)); // magenta
    colors.append(MColor(0.75f, 0.2f, 0.0f)); // brown
    colors.append(MColor(1.0f, 1.0f, 0.0f)); // yellow
    colors.append(MColor(0.62117999792099f, 0.6299999952316284f, 0.1889999955892563f)); // dark_yellow
    colors.append(MColor(1.0f, 0.5f, 0.0f)); // orange

    return MS::kSuccess;
}

void Point::draw(M3dView& view, const MDagPath& mdag_path, 
                 M3dView::DisplayStyle display_style, 
                 M3dView::DisplayStatus display_status) {

    MObject self = thisMObject();

    int display = MPlug(self, input_display).asInt();
    int use_box = MPlug(self, input_box).asInt();
    int use_cross = MPlug(self, input_cross).asInt();
    int use_tick = MPlug(self, input_tick).asInt();
    int use_axis = MPlug(self, input_axis).asInt();
    int color_index = MPlug(self, input_color).asInt();

    if (display == 0) {
        return;
    }

    MPlug local_position = MFnDependencyNode(thisMObject()).findPlug("localPosition");
    float tx = local_position.child(0).asFloat();
    float ty = local_position.child(1).asFloat();
    float tz = local_position.child(2).asFloat();

    MPlug local_scale = MFnDependencyNode(thisMObject()).findPlug("localScale");
    float sx = local_scale.child(0).asFloat();
    float sy = local_scale.child(1).asFloat();
    float sz = local_scale.child(2).asFloat();

    MColor color;
    switch (display_status) {
    case M3dView::kActive:
        color = MColor(1.0f, 1.0f, 1.0f);
        break;
    case M3dView::kLead:
        color = MColor(0.26f, 1.0f, 0.64f);
        break;
    case M3dView::kActiveAffected:
        color = MColor(0.783999979496f, 0.0f, 0.783999979496f);
        break;
    case M3dView::kTemplate:
        color = MColor(0.469999998808f, 0.469999998808f, 0.469999998808f);
        break;
    case M3dView::kActiveTemplate:
        color = MColor(1.0f, 0.689999997616f, 0.689999997616f);
        break;
    default:
        color = colors[color_index];
    }

    view.beginGL();

    if (use_axis == 1) {
        view.setDrawColor(MColor(1.0, 0, 0));
        view.drawText("x", MPoint(sx + tx, ty, tz), M3dView::kCenter);

        view.setDrawColor(MColor(0, 1.0, 0));
        view.drawText("y", MPoint(tx, sy + ty, tz), M3dView::kCenter);

        view.setDrawColor(MColor(0, 0, 1.0));
        view.drawText("z", MPoint(tx, ty, sz + tz), M3dView::kCenter);
    }

    glPushAttrib(GL_CURRENT_BIT);
    glEnable(GL_BLEND);
    glBegin(GL_LINES);

    if (use_box == 1) {
        glColor3f(color.r, color.g, color.b);

        // Top
        glVertex3f(-sx + tx, sy + ty, -sz + tz);
        glVertex3f(sx + tx, sy + ty, -sz + tz);

        glVertex3f(sx + tx, sy + ty, -sz + tz);
        glVertex3f(sx + tx, sy + ty, sz + tz);

        glVertex3f(sx + tx, sy + ty, sz + tz);
        glVertex3f(-sx + tx, sy + ty, sz + tz);

        glVertex3f(-sx + tx, sy + ty, sz + tz);
        glVertex3f(-sx + tx, sy + ty, -sz + tz);

        // Bottom
        glVertex3f(-sx + tx, -sy + ty, -sz + tz);
        glVertex3f(sx + tx, -sy + ty, -sz + tz);

        glVertex3f(sx + tx, -sy + ty, -sz + tz);
        glVertex3f(sx + tx, -sy + ty, sz + tz);

        glVertex3f(sx + tx, -sy + ty, sz + tz);
        glVertex3f(-sx + tx, -sy + ty, sz + tz);

        glVertex3f(-sx + tx, -sy + ty, sz + tz);
        glVertex3f(-sx + tx, -sy + ty, -sz + tz);

        // Left
        glVertex3f(-sx + tx, -sy + ty, -sz + tz);
        glVertex3f(-sx + tx, sy + ty, -sz + tz);

        glVertex3f(-sx + tx, sy + ty, -sz + tz);
        glVertex3f(-sx + tx, sy + ty, sz + tz);

        glVertex3f(-sx + tx, sy + ty, sz + tz);
        glVertex3f(-sx + tx, -sy + ty, sz + tz);

        glVertex3f(-sx + tx, -sy + ty, sz + tz);
        glVertex3f(-sx + tx, -sy + ty, -sz + tz);

        // Right
        glVertex3f(sx + tx, -sy + ty, -sz + tz);
        glVertex3f(sx + tx, sy + ty, -sz + tz);

        glVertex3f(sx + tx, sy + ty, -sz + tz);
        glVertex3f(sx + tx, sy + ty, sz + tz);

        glVertex3f(sx + tx, sy + ty, sz + tz);
        glVertex3f(sx + tx, -sy + ty, sz + tz);

        glVertex3f(sx + tx, -sy + ty, sz + tz);
        glVertex3f(sx + tx, -sy + ty, -sz + tz);
    }

    if (use_cross == 1) {
        glColor3f(color.r, color.g, color.b);

        glVertex3f(tx, -sy + ty, tz);
        glVertex3f(tx, sy + ty, tz);

        glVertex3f(-sx + tx, ty, tz);
        glVertex3f(sx + tx, ty, tz);

        glVertex3f(tx, ty, -sz + tz);
        glVertex3f(tx, ty, sz + tz);
    }

    if (use_tick == 1) {
        glColor3f(color.r, color.g, color.b);

        glVertex3f((-sx*0.05f) + tx, (sy*0.05f) + ty, tz);
        glVertex3f((sx*0.05f) + tx, (-sy*0.05f) + ty, tz);

        glVertex3f((sx*0.05f) + tx, (sy*0.05f) + ty, tz);
        glVertex3f((-sx*0.05f) + tx, (-sy*0.05f) + ty, tz);

        glVertex3f(tx, (sy*0.05f) + ty, (-sz*0.05f) + tz);
        glVertex3f(tx, (-sy*0.05f) + ty, (sz*0.05f) + tz);

        glVertex3f(tx, (sy*0.05f) + ty, (sz*0.05f) + tz);
        glVertex3f(tx, (-sy*0.05f) + ty, (-sz*0.05f) + tz);

        glVertex3f((sx*0.05f) + tx, ty, (-sz*0.05f) + tz);
        glVertex3f((-sx*0.05f) + tx, ty, (sz*0.05f) + tz);

        glVertex3f((sx*0.05f) + tx, ty, (sz*0.05f) + tz);
        glVertex3f((-sx*0.05f) + tx, ty, (-sz*0.05f) + tz);
    }

    if (use_axis == 1) {
        glColor3f(color.r, color.g, color.b);

        if (display_status == M3dView::kDormant) {
            glColor3f(1.0f, 0.0f, 0.0f);
        }
        glVertex3f(tx, ty, tz);
        glVertex3f(sx + tx, ty, tz);

        if (display_status == M3dView::kDormant) {
            glColor3f(0.0f, 1.0f, 0.0f);
        }
        glVertex3f(tx, ty, tz);
        glVertex3f(tx, sy + ty, tz);

        if (display_status == M3dView::kDormant) {
            glColor3f(0.0f, 0.0f, 1.0f);
        }
        glVertex3f(tx, ty, tz);
        glVertex3f(tx, ty, sz + tz);
    }

    glEnd();
    glDisable(GL_BLEND);
    glPopAttrib();

    view.endGL();
}

Edit

I was commenting portions of code to figure out where the slowdown is, and it looks like as soon as I uncomment gl draw methods the performance drops from 300 fps to 80 fps. Whaddup with that??

Green Cell
  • 4,677
  • 2
  • 18
  • 49

2 Answers2

3

I guess you are using a recent version of Maya and the Maya Viewport 2.0 vs the legacy viewport. But you are using the legacy viewport way of coding, which slow down the vieport pipeline. You are also doing this:

MPlug local_position = MFnDependencyNode(thisMObject()).findPlug("localPosition");

while you could do this instead and avoid a search which is time consuming

MPlug plug (thisMObject (), MPxLocatorNode::localPosition) ;

MPxLocatorNode::localPosition being the static MObject member of the MPxLocator class representing the "localPosition" attribute.

cyrille
  • 2,616
  • 1
  • 10
  • 18
  • Thanks! I managed to get it 10% faster by removing `findPlug`. I did both benchmarks in the legacy viewport so it should be fair play. I would implement draw for viewport 2.0 myself, but it makes my head want to explode on how complicated it looks. – Green Cell Mar 26 '16 at 02:40
  • yes, but this is the only way to get some performance improvements, if you still use GL code, even on VP2, you won't get better – cyrille Apr 02 '16 at 17:42
  • Is there a decent example somewhere on how to implement it? Every one I found was either incomplete or a bit too complicated. – Green Cell Apr 03 '16 at 02:05
0

Before I had 1000 nodes running at 72 fps, and now I got it to 270 fps.

Honestly I'm a bit disappointed that it's still slower than Maya's locator, but at least this is more doable.

I found that reducing calls to MPlugs in the draw method improved performance significantly. The idea was to use private properties instead, and only use MPlugs when the attributes get dirty. I was able to do this with MPxNode::setDependentsDirty to update the private variables with the plug values.

I also used MPxLocatorNode::isBounded and MPxLocatorNode::boundingBox. This doesn't make the node itself faster, but it won't calculate if it's outside of the camera's view, so it'll make the scene faster.

Like cyrille said in his answer, I think the difference now is that I'm using GL calls for drawing, so please feel free to share any good examples to draw in viewport 2.0.

My updated cpp file:

#include "point.h"

MTypeId Point::id(0x00000900);
MObject Point::input_display;
MObject Point::input_box;
MObject Point::input_cross;
MObject Point::input_tick;
MObject Point::input_axis;
MObject Point::input_color;
MColorArray Point::_colors;


Point::Point() {
}

void Point::postConstructor() {
    MObject self = thisMObject();
    MFnDependencyNode fn_node(self);
    fn_node.setName("pointShape#");

    _self = self;
    _update_attrs = true;
}

Point::~Point() {
}

void* Point::creator() {
    return new Point();
}

MStatus Point::initialize() {
    MFnNumericAttribute nAttr;

    input_display = nAttr.create("display", "display", MFnNumericData::kBoolean, true);
    nAttr.setKeyable(true);
    addAttribute(input_display);

    input_box = nAttr.create("box", "box", MFnNumericData::kBoolean, false);
    nAttr.setKeyable(true);
    addAttribute(input_box);

    input_cross = nAttr.create("cross", "cross", MFnNumericData::kBoolean, true);
    nAttr.setKeyable(true);
    addAttribute(input_cross);

    input_tick = nAttr.create("tick", "tick", MFnNumericData::kBoolean, false);
    nAttr.setKeyable(true);
    addAttribute(input_tick);

    input_axis = nAttr.create("axis", "axis", MFnNumericData::kBoolean, false);
    nAttr.setKeyable(true);
    addAttribute(input_axis);

    MFnEnumAttribute eAttr;

    input_color = eAttr.create("color", "color", MFnData::kNumeric);

    eAttr.addField("Black", 0);
    eAttr.addField("Grey", 1);
    eAttr.addField("White", 2);
    eAttr.addField("Red", 3);
    eAttr.addField("Light red", 4);
    eAttr.addField("Dark red", 5);
    eAttr.addField("Green", 6);
    eAttr.addField("Light green", 7);
    eAttr.addField("Dark green", 8);
    eAttr.addField("Blue", 9);
    eAttr.addField("Light blue", 10);
    eAttr.addField("Dark blue", 11);
    eAttr.addField("Purple", 12);
    eAttr.addField("Magenta", 13);
    eAttr.addField("Brown", 14);
    eAttr.addField("Yellow", 15);
    eAttr.addField("Dark yellow", 16);
    eAttr.addField("Orange", 17);

    eAttr.setDefault(8);
    eAttr.setKeyable(true);
    eAttr.setStorable(true);
    addAttribute(input_color);

    _colors.append(MColor(0.0f, 0.0f, 0.0f)); // black
    _colors.append(MColor(0.5f, 0.5f, 0.5f)); // grey
    _colors.append(MColor(1.0f, 1.0f, 1.0f)); // white
    _colors.append(MColor(1.0f, 0.0f, 0.0f)); // red
    _colors.append(MColor(1.0f, 0.6899999976158142f, 0.6899999976158142f)); // light_red
    _colors.append(MColor(0.5f, 0.0f, 0.0f)); // dark_red
    _colors.append(MColor(0.0f, 1.0f, 0.0f)); // green
    _colors.append(MColor(0.5f, 1.0f, 0.5f)); // light_green
    _colors.append(MColor(0.0f, 0.25f, 0.0f)); // dark_green
    _colors.append(MColor(0.1889999955892563f, 0.6299999952316284f, 0.6299999952316284f)); // blue
    _colors.append(MColor(0.3919999897480011f, 0.8629999756813049f, 1.0f)); // light_blue
    _colors.append(MColor(0.0f, 0.01600000075995922f, 0.37599998712539673f)); // dark_blue
    _colors.append(MColor(0.25f, 0.0f, 0.25f)); // purple
    _colors.append(MColor(1.0f, 0.0f, 1.0f)); // magenta
    _colors.append(MColor(0.75f, 0.2f, 0.0f)); // brown
    _colors.append(MColor(1.0f, 1.0f, 0.0f)); // yellow
    _colors.append(MColor(0.62117999792099f, 0.6299999952316284f, 0.1889999955892563f)); // dark_yellow
    _colors.append(MColor(1.0f, 0.5f, 0.0f)); // orange

    return MS::kSuccess;
}

bool Point::isBounded() const {
    return true;
}

MBoundingBox Point::boundingBox() const {
    MBoundingBox bbox;
    bbox.expand(MVector(1.0, 0.0, 0.0));
    bbox.expand(MVector(-1.0, 0.0, 0.0));
    bbox.expand(MVector(0.0, 1.0, 0.0));
    bbox.expand(MVector(0.0, -1.0, 0.0));
    bbox.expand(MVector(0.0, 0.0, 1.0));
    bbox.expand(MVector(0.0, 0.0, -1.0));
    return bbox;
}

MStatus Point::compute(const MPlug& plug, MDataBlock& data) {
    return MS::kUnknownParameter;
}

MStatus Point::setDependentsDirty(const MPlug& dirty_plug, MPlugArray& affected_plugs) {
    MString plug_name_MString = dirty_plug.partialName();
    std::string plug_name = plug_name_MString.asChar();
    if (plug_name == "display") {
        _update_attrs = true;
    } 
    else if (plug_name == "box") {
        _update_attrs = true;
    }
    else if (plug_name == "cross") {
        _update_attrs = true;
    }
    else if (plug_name == "tick") {
        _update_attrs = true;
    }
    else if (plug_name == "axis") {
        _update_attrs = true;
    }
    else if (plug_name == "color") {
        _update_attrs = true;
    }
    else if (plug_name == "lpx") {
        _update_attrs = true;
    }
    else if (plug_name == "lpy") {
        _update_attrs = true;
    }
    else if (plug_name == "lpz") {
        _update_attrs = true;
    }
    else if (plug_name == "lsx") {
        _update_attrs = true;
    }
    else if (plug_name == "lsy") {
        _update_attrs = true;
    }
    else if (plug_name == "lsz") {
        _update_attrs = true;
    }
    return MS::kSuccess;
}

void Point::draw(M3dView& view, const MDagPath& mdag_path, 
                 M3dView::DisplayStyle display_style, 
                 M3dView::DisplayStatus display_status) {

    if (Point::_update_attrs) {
        _display = MPlug(_self, Point::input_display).asBool();
        _box = MPlug(_self, Point::input_box).asBool();
        _cross = MPlug(_self, Point::input_cross).asBool();
        _tick = MPlug(_self, Point::input_tick).asBool();
        _axis = MPlug(_self, Point::input_axis).asBool();
        _color = MPlug(_self, Point::input_color).asShort();

        _tx = MPlug(_self, Point::localPositionX).asFloat();
        _ty = MPlug(_self, Point::localPositionY).asFloat();
        _tz = MPlug(_self, Point::localPositionZ).asFloat();

        _sx = MPlug(_self, Point::localScaleX).asFloat();
        _sy = MPlug(_self, Point::localScaleY).asFloat();
        _sz = MPlug(_self, Point::localScaleZ).asFloat();

        _update_attrs = false;
    }

    if (! _display) {
        return;
    }

    MColor color;
    switch (display_status) {
    case M3dView::kActive:
        color = MColor(1.0f, 1.0f, 1.0f);
        break;
    case M3dView::kLead:
        color = MColor(0.26f, 1.0f, 0.64f);
        break;
    case M3dView::kActiveAffected:
        color = MColor(0.783999979496f, 0.0f, 0.783999979496f);
        break;
    case M3dView::kTemplate:
        color = MColor(0.469999998808f, 0.469999998808f, 0.469999998808f);
        break;
    case M3dView::kActiveTemplate:
        color = MColor(1.0f, 0.689999997616f, 0.689999997616f);
        break;
    default:
        color = _colors[_color];
    }

    view.beginGL();

    if (_axis) {
        view.setDrawColor(MColor(1.0, 0, 0));
        view.drawText("x", MPoint(_sx + _tx, _ty, _tz), M3dView::kCenter);

        view.setDrawColor(MColor(0, 1.0, 0));
        view.drawText("y", MPoint(_tx, _sy + _ty, _tz), M3dView::kCenter);

        view.setDrawColor(MColor(0, 0, 1.0));
        view.drawText("z", MPoint(_tx, _ty, _sz + _tz), M3dView::kCenter);
    }

    glPushAttrib(GL_CURRENT_BIT);
    glBegin(GL_LINES);

    if (_box) {
        glColor3f(color.r, color.g, color.b);

        // Top rect
        glVertex3f(-_sx + _tx, _sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, _sy + _ty, -_sz + _tz);

        glVertex3f(_sx + _tx, _sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, _sy + _ty, _sz + _tz);

        glVertex3f(_sx + _tx, _sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, _sy + _ty, _sz + _tz);

        glVertex3f(-_sx + _tx, _sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, _sy + _ty, -_sz + _tz);

        // Bottom rect
        glVertex3f(-_sx + _tx, -_sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, -_sy + _ty, -_sz + _tz);

        glVertex3f(_sx + _tx, -_sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, -_sy + _ty, _sz + _tz);

        glVertex3f(_sx + _tx, -_sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, -_sy + _ty, _sz + _tz);

        glVertex3f(-_sx + _tx, -_sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, -_sy + _ty, -_sz + _tz);

        // Left rect
        glVertex3f(-_sx + _tx, -_sy + _ty, -_sz + _tz);
        glVertex3f(-_sx + _tx, _sy + _ty, -_sz + _tz);

        glVertex3f(-_sx + _tx, _sy + _ty, -_sz + _tz);
        glVertex3f(-_sx + _tx, _sy + _ty, _sz + _tz);

        glVertex3f(-_sx + _tx, _sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, -_sy + _ty, _sz + _tz);

        glVertex3f(-_sx + _tx, -_sy + _ty, _sz + _tz);
        glVertex3f(-_sx + _tx, -_sy + _ty, -_sz + _tz);

        // Right rect
        glVertex3f(_sx + _tx, -_sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, _sy + _ty, -_sz + _tz);

        glVertex3f(_sx + _tx, _sy + _ty, -_sz + _tz);
        glVertex3f(_sx + _tx, _sy + _ty, _sz + _tz);

        glVertex3f(_sx + _tx, _sy + _ty, _sz + _tz);
        glVertex3f(_sx + _tx, -_sy + _ty, _sz + _tz);

        glVertex3f(_sx + _tx, -_sy + _ty, _sz + _tz);
        glVertex3f(_sx + _tx, -_sy + _ty, -_sz + _tz);
    }

    if (_cross) {
        glColor3f(color.r, color.g, color.b);

        glVertex3f(_tx, -_sy + _ty, _tz);
        glVertex3f(_tx, _sy + _ty, _tz);

        glVertex3f(-_sx + _tx, _ty, _tz);
        glVertex3f(_sx + _tx, _ty, _tz);

        glVertex3f(_tx, _ty, -_sz + _tz);
        glVertex3f(_tx, _ty, _sz + _tz);
    }

    if (_tick) {
        glColor3f(color.r, color.g, color.b);

        glVertex3f((-_sx*0.05f) + _tx, (_sy*0.05f) + _ty, _tz);
        glVertex3f((_sx*0.05f) + _tx, (-_sy*0.05f) + _ty, _tz);

        glVertex3f((_sx*0.05f) + _tx, (_sy*0.05f) + _ty, _tz);
        glVertex3f((-_sx*0.05f) + _tx, (-_sy*0.05f) + _ty, _tz);

        glVertex3f(_tx, (_sy*0.05f) + _ty, (-_sz*0.05f) + _tz);
        glVertex3f(_tx, (-_sy*0.05f) + _ty, (_sz*0.05f) + _tz);

        glVertex3f(_tx, (_sy*0.05f) + _ty, (_sz*0.05f) + _tz);
        glVertex3f(_tx, (-_sy*0.05f) + _ty, (-_sz*0.05f) + _tz);

        glVertex3f((_sx*0.05f) + _tx, _ty, (-_sz*0.05f) + _tz);
        glVertex3f((-_sx*0.05f) + _tx, _ty, (_sz*0.05f) + _tz);

        glVertex3f((_sx*0.05f) + _tx, _ty, (_sz*0.05f) + _tz);
        glVertex3f((-_sx*0.05f) + _tx, _ty, (-_sz*0.05f) + _tz);
    }

    if (_axis) {
        glColor3f(color.r, color.g, color.b);

        if (display_status == M3dView::kDormant) {
            glColor3f(1.0f, 0.0f, 0.0f);
        }
        glVertex3f(_tx, _ty, _tz);
        glVertex3f(_sx + _tx, _ty, _tz);

        if (display_status == M3dView::kDormant) {
            glColor3f(0.0f, 1.0f, 0.0f);
        }
        glVertex3f(_tx, _ty, _tz);
        glVertex3f(_tx, _sy + _ty, _tz);

        if (display_status == M3dView::kDormant) {
            glColor3f(0.0f, 0.0f, 1.0f);
        }
        glVertex3f(_tx, _ty, _tz);
        glVertex3f(_tx, _ty, _sz + _tz);
    }

    glEnd();
    glPopAttrib();

    view.endGL();
}
Green Cell
  • 4,677
  • 2
  • 18
  • 49