优化 MPxLocatorNode 绘制
Optimizing MPxLocatorNode draw
我用 C++ 中的 Maya api 创建了一个 MPxLocatorNode
。该节点没有compute
方法,它只是在draw
方法中使用open gl绘制的不同样式的形状。
它绘制的一种样式是十字,与定位器完全相同。因此,我进行了一些基准测试,将其与本机定位器进行比较,发现我的节点性能要慢得多。 Maya 的定位器大约快 4 倍!
1000 个节点
我的节点:74 fps
Maya 的定位器:300 fps
我做错了什么会降低节点的性能?我唯一能想到的是,我在 draw
方法中通过 MPlug
获取节点的 MObjects
,这与在 compute
中从数据块中获取它们不同]方法。
我的cpp文件在下面。大部分减速应该在draw方法中。
#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();
}
编辑
我正在评论部分代码以找出减速的位置,看起来只要我取消注释 gl draw 方法,性能就会从 300 fps 下降到 80 fps。怎么了??
我猜您使用的是最新版本的 Maya 和 Maya Viewport 2.0 与旧版视口。但是您使用的是旧式视口编码方式,这会减慢视口管道。
你也在这样做:
MPlug local_position = MFnDependencyNode(thisMObject()).findPlug("localPosition");
虽然您可以改为执行此操作并避免耗时的搜索
MPlug plug (thisMObject (), MPxLocatorNode::localPosition) ;
MPxLocatorNode::localPosition 是 MPxLocator class 的静态 MObject 成员,表示 "localPosition" 属性。
之前我有 1000 个节点 运行 72 fps,现在我达到了 270 fps。
老实说,我有点失望,它仍然比 Maya 的定位器慢,但至少这更可行。
我发现在 draw
方法中减少对 MPlugs
的调用可以显着提高性能。想法是改用私有属性,并且仅在属性变脏时才使用 MPlugs
。我能够使用 MPxNode::setDependentsDirty
来使用插件值更新私有变量。
我还用了MPxLocatorNode::isBounded
和MPxLocatorNode::boundingBox
。这不会使节点本身更快,但它不会计算它是否在相机的视野之外,因此它会使场景更快。
就像 cyrille 在他的回答中所说的那样,我认为现在的不同之处在于我正在使用 GL 调用进行绘图,所以请随时分享在视口 2.0 中绘制的任何好的示例。
我更新的 cpp 文件:
#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();
}
我用 C++ 中的 Maya api 创建了一个 MPxLocatorNode
。该节点没有compute
方法,它只是在draw
方法中使用open gl绘制的不同样式的形状。
它绘制的一种样式是十字,与定位器完全相同。因此,我进行了一些基准测试,将其与本机定位器进行比较,发现我的节点性能要慢得多。 Maya 的定位器大约快 4 倍!
1000 个节点
我的节点:74 fps
Maya 的定位器:300 fps
我做错了什么会降低节点的性能?我唯一能想到的是,我在 draw
方法中通过 MPlug
获取节点的 MObjects
,这与在 compute
中从数据块中获取它们不同]方法。
我的cpp文件在下面。大部分减速应该在draw方法中。
#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();
}
编辑
我正在评论部分代码以找出减速的位置,看起来只要我取消注释 gl draw 方法,性能就会从 300 fps 下降到 80 fps。怎么了??
我猜您使用的是最新版本的 Maya 和 Maya Viewport 2.0 与旧版视口。但是您使用的是旧式视口编码方式,这会减慢视口管道。 你也在这样做:
MPlug local_position = MFnDependencyNode(thisMObject()).findPlug("localPosition");
虽然您可以改为执行此操作并避免耗时的搜索
MPlug plug (thisMObject (), MPxLocatorNode::localPosition) ;
MPxLocatorNode::localPosition 是 MPxLocator class 的静态 MObject 成员,表示 "localPosition" 属性。
之前我有 1000 个节点 运行 72 fps,现在我达到了 270 fps。
老实说,我有点失望,它仍然比 Maya 的定位器慢,但至少这更可行。
我发现在 draw
方法中减少对 MPlugs
的调用可以显着提高性能。想法是改用私有属性,并且仅在属性变脏时才使用 MPlugs
。我能够使用 MPxNode::setDependentsDirty
来使用插件值更新私有变量。
我还用了MPxLocatorNode::isBounded
和MPxLocatorNode::boundingBox
。这不会使节点本身更快,但它不会计算它是否在相机的视野之外,因此它会使场景更快。
就像 cyrille 在他的回答中所说的那样,我认为现在的不同之处在于我正在使用 GL 调用进行绘图,所以请随时分享在视口 2.0 中绘制的任何好的示例。
我更新的 cpp 文件:
#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();
}