void ccMaterial::applyGL(const QOpenGLContext* context, bool lightEnabled, bool skipDiffuse) const { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1* glFunc = context->versionFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; if (lightEnabled) { if (!skipDiffuse) { glFunc->glMaterialfv(GL_FRONT, GL_DIFFUSE, m_diffuseFront.rgba); glFunc->glMaterialfv(GL_BACK, GL_DIFFUSE, m_diffuseBack.rgba); } glFunc->glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_ambient.rgba); glFunc->glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_specular.rgba); glFunc->glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, m_emission.rgba); glFunc->glMaterialf (GL_FRONT, GL_SHININESS, std::max(0.0f, std::min(m_shininessFront, 128.0f))); glFunc->glMaterialf (GL_BACK, GL_SHININESS, std::max(0.0f, std::min(m_shininessBack, 128.0f))); } else { glFunc->glColor4fv(m_diffuseFront.rgba); } }
void ccMaterial::MakeLightsNeutral(const QOpenGLContext* context) { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1* glFunc = context->versionFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; GLint maxLightCount; glFunc->glGetIntegerv(GL_MAX_LIGHTS, &maxLightCount); for (int i = 0; i < maxLightCount; ++i) { if (glFunc->glIsEnabled(GL_LIGHT0 + i)) { float diffuse[4]; float ambiant[4]; float specular[4]; glFunc->glGetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, diffuse); glFunc->glGetLightfv(GL_LIGHT0 + i, GL_AMBIENT, ambiant); glFunc->glGetLightfv(GL_LIGHT0 + i, GL_SPECULAR, specular); diffuse[0] = diffuse[1] = diffuse[2] = ( diffuse[0] + diffuse[1] + diffuse[2]) / 3; //'mean' (gray) value ambiant[0] = ambiant[1] = ambiant[2] = ( ambiant[0] + ambiant[1] + ambiant[2]) / 3; //'mean' (gray) value specular[0] = specular[1] = specular[2] = (specular[0] + specular[1] + specular[2]) / 3; //'mean' (gray) value glFunc->glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, diffuse); glFunc->glLightfv(GL_LIGHT0 + i, GL_AMBIENT, ambiant); glFunc->glLightfv(GL_LIGHT0 + i, GL_SPECULAR, specular); } } }
void ccHObject::drawBB(CC_DRAW_CONTEXT& context, const ccColor::Rgb& col) { QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(1.0f); switch (m_selectionBehavior) { case SELECTION_AA_BBOX: getDisplayBB_recursive(true, m_currentDisplay).draw(context, col); break; case SELECTION_FIT_BBOX: { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) break; ccGLMatrix trans; ccBBox box = getOwnFitBB(trans); if (box.isValid()) { glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glMultMatrixf(trans.data()); box.draw(context, col); glFunc->glPopMatrix(); } } break; case SELECTION_IGNORED: break; default: assert(false); } glFunc->glPopAttrib(); //GL_LINE_BIT }
static void DrawUnitCross(int ID, const CCVector3& center, PointCoordinateType scale, const ccColor::Rgb& col, CC_DRAW_CONTEXT& context) { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; if (ID > 0) glFunc->glLoadName(ID); scale /= 2; DrawUnitArrow(0, center, CCVector3(-1, 0, 0), scale, col, context); DrawUnitArrow(0, center, CCVector3( 1, 0, 0), scale, col, context); DrawUnitArrow(0, center, CCVector3( 0,-1, 0), scale, col, context); DrawUnitArrow(0, center, CCVector3( 0, 1, 0), scale, col, context); DrawUnitArrow(0, center, CCVector3( 0, 0,-1), scale, col, context); DrawUnitArrow(0, center, CCVector3( 0, 0, 1), scale, col, context); }
void DrawUnitArrow(int ID, const CCVector3& start, const CCVector3& direction, PointCoordinateType scale, const ccColor::Rgb& col, CC_DRAW_CONTEXT& context) { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; if (ID > 0) { glFunc->glLoadName(ID); } glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); ccGL::Translate(glFunc, start.x, start.y, start.z); ccGL::Scale(glFunc, scale, scale, scale); //we compute scalar prod between the two vectors CCVector3 Z(0.0,0.0,1.0); PointCoordinateType ps = Z.dot(direction); if (ps < 1) { CCVector3 axis(1,0,0); PointCoordinateType angle_deg = static_cast<PointCoordinateType>(180.0); if (ps > -1) { //we deduce angle from scalar prod angle_deg = acos(ps) * static_cast<PointCoordinateType>(CC_RAD_TO_DEG); //we compute rotation axis with scalar prod axis = Z.cross(direction); } ccGL::Rotate(glFunc,angle_deg, axis.x, axis.y, axis.z); } if (!c_arrowShaft) c_arrowShaft = QSharedPointer<ccCylinder>(new ccCylinder(0.15f,0.6f,0,"ArrowShaft",12)); if (!c_arrowHead) c_arrowHead = QSharedPointer<ccCone>(new ccCone(0.3f,0,0.4f,0,0,0,"ArrowHead",24)); glFunc->glTranslatef(0,0,0.3f); c_arrowShaft->setTempColor(col); c_arrowShaft->draw(context); glFunc->glTranslatef(0,0,0.3f+0.2f); c_arrowHead->setTempColor(col); c_arrowHead->draw(context); glFunc->glPopMatrix(); }
void ccSample::drawStratPos(CC_DRAW_CONTEXT& context) { if (MACRO_Draw3D(context)) { QOpenGLFunctions_2_1* glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); QFont font(context.display->getTextDisplayFont()); // takes rendering zoom into // account! font.setPointSize(font.pointSize()); font.setBold(true); // // draw their name // glPushAttrib(GL_DEPTH_BUFFER_BIT); glFunc->glDisable(GL_DEPTH_TEST); QString name = QString::number(getSample()->getStratigraphicPosition(), 'g', 3); context.display->display3DLabel(name, CCVector3(getSample()->getPosition().data()), ccColor::red.rgb, font); // CCVector3 p (x,y,z); // QString title = (getName()); // context.display->display3DLabel( title, // p + CCVector3( // context.pickedPointsTextShift, // context.pickedPointsTextShift, // context.pickedPointsTextShift), // ccColor::magenta, // font ); // glPopAttrib(); glFunc->glEnable(GL_DEPTH_TEST); } }
static void DrawUnitTorus(int ID, const CCVector3& center, const CCVector3& direction, PointCoordinateType scale, const ccColor::Rgb& col, CC_DRAW_CONTEXT& context) { //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; if (ID > 0) glFunc->glLoadName(ID); glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); ccGL::Translate(glFunc, center.x, center.y, center.z); ccGL::Scale(glFunc, scale, scale, scale); //we compute scalar prod between the two vectors CCVector3 Z(0,0,1); PointCoordinateType ps = Z.dot(direction); if (ps < 1) { CCVector3 axis(1,0,0); PointCoordinateType angle_deg = 180; if (ps > -1) { //we deduce angle from scalar prod angle_deg = acos(ps) * static_cast<PointCoordinateType>(CC_RAD_TO_DEG); //we compute rotation axis with scalar prod axis = Z.cross(direction); } ccGL::Rotate(glFunc, angle_deg, axis.x, axis.y, axis.z); } if (!c_torus) c_torus = QSharedPointer<ccTorus>(new ccTorus(0.2f, 0.4f, 2.0*M_PI, false, 0, 0, "Torus", 12)); glFunc->glTranslatef(0,0,0.3f); c_torus->setTempColor(col); c_torus->draw(context); glFunc->glPopMatrix(); }
void cc2DLabel::drawMeOnly2D(CC_DRAW_CONTEXT& context) { if (!m_dispIn2D) return; assert(!m_points.empty()); //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) { glFunc->glPushName(getUniqueID()); } //we should already be in orthoprojective & centered omde //glFunc->glOrtho(-halfW,halfW,-halfH,halfH,-maxS,maxS); //label title const int precision = context.dispNumberPrecision; QString title = getTitle(precision); #define DRAW_CONTENT_AS_TAB #ifdef DRAW_CONTENT_AS_TAB //draw contents as an array Tab tab(4); int rowHeight = 0; #else //simply display the content as text QStringList body; #endif //render zoom int margin = static_cast<int>(c_margin * context.renderZoom); int tabMarginX = static_cast<int>(c_tabMarginX * context.renderZoom); int tabMarginY = static_cast<int>(c_tabMarginY * context.renderZoom); int arrowBaseSize = static_cast<int>(c_arrowBaseSize * context.renderZoom); int titleHeight = 0; GLdouble arrowDestX = -1.0, arrowDestY = -1.0; QFont bodyFont,titleFont; if (!pushName) { /*** line from 2D point to label ***/ //compute arrow head position CCVector3 arrowDest; m_points[0].cloud->getPoint(m_points[0].index,arrowDest); for (unsigned i = 1; i < m_points.size(); ++i) { arrowDest += *m_points[i].cloud->getPointPersistentPtr(m_points[i].index); } arrowDest /= static_cast<PointCoordinateType>(m_points.size()); //project it in 2D screen coordinates { ccGLCameraParameters camera; context.display->getGLCameraParameters(camera); CCVector3d Q2D; camera.project(arrowDest, Q2D); arrowDestX = Q2D.x; arrowDestY = Q2D.y; } /*** label border ***/ bodyFont = context.display->getLabelDisplayFont(); //takes rendering zoom into account! titleFont = bodyFont; //takes rendering zoom into account! //titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); titleHeight = titleFontMetrics.height(); QFontMetrics bodyFontMetrics(bodyFont); rowHeight = bodyFontMetrics.height(); //get label box dimension int dx = 100; int dy = 0; //int buttonSize = static_cast<int>(c_buttonSize * context.renderZoom); { //base box dimension dx = std::max(dx,titleFontMetrics.width(title)); dy += margin; //top vertical margin dy += titleHeight; //title if (m_showFullBody) { #ifdef DRAW_CONTENT_AS_TAB try { size_t labelCount = m_points.size(); if (labelCount == 1) { LabelInfo1 info; getLabelInfo1(info); bool isShifted = info.cloud->isShifted(); //1st block: X, Y, Z (local) { int c = tab.add2x3Block(); QChar suffix; if (isShifted) suffix = 'l'; //'l' for local const CCVector3* P = info.cloud->getPoint(info.pointIndex); tab.colContent[c] << QString("X") + suffix; tab.colContent[c+1] << QString::number(P->x,'f',precision); tab.colContent[c] << QString("Y") + suffix; tab.colContent[c+1] << QString::number(P->y,'f',precision); tab.colContent[c] << QString("Z") + suffix; tab.colContent[c+1] << QString::number(P->z,'f',precision); } //next block: X, Y, Z (global) if (isShifted) { int c = tab.add2x3Block(); CCVector3d P = info.cloud->toGlobal3d(*info.cloud->getPoint(info.pointIndex)); tab.colContent[c] << "Xg"; tab.colContent[c+1] << QString::number(P.x,'f',precision); tab.colContent[c] << "Yg"; tab.colContent[c+1] << QString::number(P.y,'f',precision); tab.colContent[c] << "Zg"; tab.colContent[c+1] << QString::number(P.z,'f',precision); } //next block: normal if (info.hasNormal) { int c = tab.add2x3Block(); tab.colContent[c] << "Nx"; tab.colContent[c+1] << QString::number(info.normal.x,'f',precision); tab.colContent[c] << "Ny"; tab.colContent[c+1] << QString::number(info.normal.y,'f',precision); tab.colContent[c] << "Nz"; tab.colContent[c+1] << QString::number(info.normal.z,'f',precision); } //next block: RGB color if (info.hasRGB) { int c = tab.add2x3Block(); tab.colContent[c] <<"R"; tab.colContent[c+1] << QString::number(info.rgb.x); tab.colContent[c] <<"G"; tab.colContent[c+1] << QString::number(info.rgb.y); tab.colContent[c] <<"B"; tab.colContent[c+1] << QString::number(info.rgb.z); } } else if (labelCount == 2) { LabelInfo2 info; getLabelInfo2(info); //1st block: dX, dY, dZ { int c = tab.add2x3Block(); tab.colContent[c] << MathSymbolDelta + QString("X"); tab.colContent[c+1] << QString::number(info.diff.x,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("Y"); tab.colContent[c+1] << QString::number(info.diff.y,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("Z"); tab.colContent[c+1] << QString::number(info.diff.z,'f',precision); } //2nd block: dXY, dXZ, dZY { int c = tab.add2x3Block(); PointCoordinateType dXY = sqrt(info.diff.x*info.diff.x + info.diff.y*info.diff.y); PointCoordinateType dXZ = sqrt(info.diff.x*info.diff.x + info.diff.z*info.diff.z); PointCoordinateType dZY = sqrt(info.diff.z*info.diff.z + info.diff.y*info.diff.y); tab.colContent[c] << MathSymbolDelta + QString("XY"); tab.colContent[c+1] << QString::number(dXY,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("XZ"); tab.colContent[c+1] << QString::number(dXZ,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("ZY"); tab.colContent[c+1] << QString::number(dZY,'f',precision); } } else if (labelCount == 3) { LabelInfo3 info; getLabelInfo3(info); tab.setMaxBlockPerRow(2); //square tab (2x2 blocks) //next block: indexes { int c = tab.add2x3Block(); tab.colContent[c] << "index.A"; tab.colContent[c+1] << QString::number(info.point1Index); tab.colContent[c] << "index.B"; tab.colContent[c+1] << QString::number(info.point2Index); tab.colContent[c] << "index.C"; tab.colContent[c+1] << QString::number(info.point3Index); } //next block: edges length { int c = tab.add2x3Block(); tab.colContent[c] << "AB"; tab.colContent[c+1] << QString::number(info.edges.u[0],'f',precision); tab.colContent[c] << "BC"; tab.colContent[c+1] << QString::number(info.edges.u[1],'f',precision); tab.colContent[c] << "CA"; tab.colContent[c+1] << QString::number(info.edges.u[2],'f',precision); } //next block: angles { int c = tab.add2x3Block(); tab.colContent[c] << "angle.A"; tab.colContent[c+1] << QString::number(info.angles.u[0],'f',precision); tab.colContent[c] << "angle.B"; tab.colContent[c+1] << QString::number(info.angles.u[1],'f',precision); tab.colContent[c] << "angle.C"; tab.colContent[c+1] << QString::number(info.angles.u[2],'f',precision); } //next block: normal { int c = tab.add2x3Block(); tab.colContent[c] << "Nx"; tab.colContent[c+1] << QString::number(info.normal.x,'f',precision); tab.colContent[c] << "Ny"; tab.colContent[c+1] << QString::number(info.normal.y,'f',precision); tab.colContent[c] << "Nz"; tab.colContent[c+1] << QString::number(info.normal.z,'f',precision); } } } catch (const std::bad_alloc&) { //not enough memory return; } //compute min width of each column int totalWidth = tab.updateColumnsWidthTable(bodyFontMetrics); int tabWidth = totalWidth + tab.colCount * (2*tabMarginX); //add inner margins dx = std::max(dx,tabWidth); dy += tab.rowCount * (rowHeight + 2*tabMarginY); //add inner margins //we also add a margin every 3 rows dy += std::max(0,(tab.rowCount/3)-1) * margin; dy += margin; //bottom vertical margin #else body = getLabelContent(precision); if (!body.empty()) { dy += margin; //vertical margin above separator for (int j=0; j<body.size(); ++j) { dx = std::max(dx,bodyFontMetrics.width(body[j])); dy += rowHeight; //body line height } dy += margin; //vertical margin below text } #endif //DRAW_CONTENT_AS_TAB } dx += margin*2; // horizontal margins } //main rectangle m_labelROI = QRect(0,0,dx,dy); //close button //m_closeButtonROI.right() = dx-margin; //m_closeButtonROI.left() = m_closeButtonROI.right()-buttonSize; //m_closeButtonROI.bottom() = margin; //m_closeButtonROI.top() = m_closeButtonROI.bottom()+buttonSize; //automatically elide the title //title = titleFontMetrics.elidedText(title,Qt::ElideRight,m_closeButtonROI[0]-2*margin); } int halfW = (context.glW >> 1); int halfH = (context.glH >> 1); //draw label rectangle int xStart = static_cast<int>(context.glW * m_screenPos[0]); int yStart = static_cast<int>(context.glH * (1.0f - m_screenPos[1])); m_lastScreenPos[0] = xStart; m_lastScreenPos[1] = yStart - m_labelROI.height(); //colors bool highlighted = (!pushName && isSelected()); //default background color unsigned char alpha = static_cast<unsigned char>((context.labelOpacity/100.0) * 255); ccColor::Rgbaub defaultBkgColor(context.labelDefaultBkgCol,alpha); //default border color (mustn't be totally transparent!) ccColor::Rgbaub defaultBorderColor(ccColor::red); if (!highlighted) { //apply only half of the transparency unsigned char halfAlpha = static_cast<unsigned char>((50.0 + context.labelOpacity/200.0) * 255); defaultBorderColor = ccColor::Rgbaub(context.labelDefaultBkgCol,halfAlpha); } glFunc->glPushAttrib(GL_COLOR_BUFFER_BIT); glFunc->glEnable(GL_BLEND); glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glTranslatef(static_cast<GLfloat>(-halfW + xStart), static_cast<GLfloat>(-halfH + yStart), 0); if (!pushName) { //compute arrow base position relatively to the label rectangle (for 0 to 8) int arrowBaseConfig = 0; int iArrowDestX = static_cast<int>(arrowDestX)-xStart; int iArrowDestY = static_cast<int>(arrowDestY)-yStart; { if (iArrowDestX < m_labelROI.left()) //left arrowBaseConfig += 0; else if (iArrowDestX > m_labelROI.right()) //Right arrowBaseConfig += 2; else //Middle arrowBaseConfig += 1; if (iArrowDestY > -m_labelROI.top()) //Top arrowBaseConfig += 0; else if (iArrowDestY < -m_labelROI.bottom()) //Bottom arrowBaseConfig += 6; else //Middle arrowBaseConfig += 3; } //we make the arrow base start from the nearest corner if (arrowBaseConfig != 4) //4 = label above point! { glFunc->glColor4ubv(defaultBorderColor.rgba); glFunc->glBegin(GL_TRIANGLE_FAN); glFunc->glVertex2d(arrowDestX - xStart, arrowDestY - yStart); switch(arrowBaseConfig) { case 0: //top-left corner glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()-2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left()+2*arrowBaseSize, -m_labelROI.top()); break; case 1: //top-middle edge glFunc->glVertex2i(std::max(m_labelROI.left(),iArrowDestX-arrowBaseSize), -m_labelROI.top()); glFunc->glVertex2i(std::min(m_labelROI.right(),iArrowDestX+arrowBaseSize), -m_labelROI.top()); break; case 2: //top-right corner glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()-2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.right()-2*arrowBaseSize, -m_labelROI.top()); break; case 3: //middle-left edge glFunc->glVertex2i(m_labelROI.left(), std::min(-m_labelROI.top(),iArrowDestY+arrowBaseSize)); glFunc->glVertex2i(m_labelROI.left(), std::max(-m_labelROI.bottom(),iArrowDestY-arrowBaseSize)); break; case 4: //middle of rectangle! break; case 5: //middle-right edge glFunc->glVertex2i(m_labelROI.right(), std::min(-m_labelROI.top(),iArrowDestY+arrowBaseSize)); glFunc->glVertex2i(m_labelROI.right(), std::max(-m_labelROI.bottom(),iArrowDestY-arrowBaseSize)); break; case 6: //bottom-left corner glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()+2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.left()+2*arrowBaseSize, -m_labelROI.bottom()); break; case 7: //bottom-middle edge glFunc->glVertex2i(std::max(m_labelROI.left(),iArrowDestX-arrowBaseSize), -m_labelROI.bottom()); glFunc->glVertex2i(std::min(m_labelROI.right(),iArrowDestX+arrowBaseSize), -m_labelROI.bottom()); break; case 8: //bottom-right corner glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()+2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right()-2*arrowBaseSize, -m_labelROI.bottom()); break; } glFunc->glEnd(); } } //main rectangle glFunc->glColor4ubv(defaultBkgColor.rgba); glFunc->glBegin(GL_QUADS); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glEnd(); //if (highlighted) { glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(3.0f * context.renderZoom); glFunc->glColor4ubv(defaultBorderColor.rgba); glFunc->glBegin(GL_LINE_LOOP); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glEnd(); glFunc->glPopAttrib(); } //draw close button //glFunc->glColor3ubv(ccColor::black); //glFunc->glBegin(GL_LINE_LOOP); //glFunc->glVertex2i(m_closeButtonROI.left(),-m_closeButtonROI.top()); //glFunc->glVertex2i(m_closeButtonROI.left(),-m_closeButtonROI.bottom()); //glFunc->glVertex2i(m_closeButtonROI.right(),-m_closeButtonROI.bottom()); //glFunc->glVertex2i(m_closeButtonROI.right(),-m_closeButtonROI.top()); //glFunc->glEnd(); //glFunc->glBegin(GL_LINES); //glFunc->glVertex2i(m_closeButtonROI.left()+2,-m_closeButtonROI.top()+2); //glFunc->glVertex2i(m_closeButtonROI.right()-2,-m_closeButtonROI.bottom()-2); //glFunc->glVertex2i(m_closeButtonROI.right()-2,-m_closeButtonROI.top()+2); //glFunc->glVertex2i(m_closeButtonROI.left()+2,-m_closeButtonROI.bottom()-2); //glFunc->glEnd(); //display text if (!pushName) { int xStartRel = margin; int yStartRel = 0; yStartRel -= titleHeight; ccColor::Rgbub defaultTextColor; if (context.labelOpacity < 40) { //under a given opacity level, we use the default text color instead! defaultTextColor = context.textDefaultCol; } else { defaultTextColor = ccColor::Rgbub( 255 - context.labelDefaultBkgCol.r, 255 - context.labelDefaultBkgCol.g, 255 - context.labelDefaultBkgCol.b); } //label title context.display->displayText( title, xStart+xStartRel, yStart+yStartRel, ccGenericGLDisplay::ALIGN_DEFAULT, 0, defaultTextColor.rgb, &titleFont); yStartRel -= margin; if (m_showFullBody) { #ifdef DRAW_CONTENT_AS_TAB int xCol = xStartRel; for (int c=0; c<tab.colCount; ++c) { int width = tab.colWidth[c] + 2*tabMarginX; int height = rowHeight + 2*tabMarginY; int yRow = yStartRel; int actualRowCount = std::min(tab.rowCount,tab.colContent[c].size()); bool labelCol = ((c & 1) == 0); const unsigned char* textColor = labelCol ? ccColor::white.rgba : defaultTextColor.rgb; for (int r=0; r<actualRowCount; ++r) { if (r && (r % 3) == 0) yRow -= margin; if (labelCol) { //draw background int rgbIndex = (r % 3); if (rgbIndex == 0) glFunc->glColor3ubv(ccColor::red.rgba); else if (rgbIndex == 1) glFunc->glColor3ubv(c_darkGreen.rgba); else if (rgbIndex == 2) glFunc->glColor3ubv(ccColor::blue.rgba); glFunc->glBegin(GL_QUADS); glFunc->glVertex2i(m_labelROI.left() + xCol, -m_labelROI.top() + yRow); glFunc->glVertex2i(m_labelROI.left() + xCol, -m_labelROI.top() + yRow - height); glFunc->glVertex2i(m_labelROI.left() + xCol + width, -m_labelROI.top() + yRow - height); glFunc->glVertex2i(m_labelROI.left() + xCol + width, -m_labelROI.top() + yRow); glFunc->glEnd(); } const QString& str = tab.colContent[c][r]; int xShift = 0; if (labelCol) { //align characters in the middle xShift = (tab.colWidth[c] - QFontMetrics(bodyFont).width(str)) / 2; } else { //align digits on the right xShift = tab.colWidth[c] - QFontMetrics(bodyFont).width(str); } context.display->displayText( str, xStart + xCol + tabMarginX + xShift, yStart + yRow - rowHeight, ccGenericGLDisplay::ALIGN_DEFAULT, 0, textColor, &bodyFont); yRow -= height; } xCol += width; } #else if (!body.empty()) { //display body yStartRel -= margin; for (int i=0; i<body.size(); ++i) { yStartRel -= rowHeight; context.display->displayText(body[i],xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor.rgb,&bodyFont); } } #endif //DRAW_CONTENT_AS_TAB } } glFunc->glPopAttrib(); glFunc->glPopMatrix(); if (pushName) { glFunc->glPopName(); } }
void cc2DLabel::drawMeOnly3D(CC_DRAW_CONTEXT& context) { assert(!m_points.empty()); //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not particularily fast if (MACRO_DrawFastNamesOnly(context)) return; glFunc->glPushName(getUniqueIDForDisplay()); } const float c_sizeFactor = 4.0f; bool loop = false; size_t count = m_points.size(); switch (count) { case 3: { glFunc->glPushAttrib(GL_COLOR_BUFFER_BIT); glFunc->glEnable(GL_BLEND); //we draw the triangle glFunc->glColor4ub(255,255,0,128); glFunc->glBegin(GL_TRIANGLES); ccGL::Vertex3v(glFunc, m_points[0].cloud->getPoint(m_points[0].index)->u); ccGL::Vertex3v(glFunc, m_points[1].cloud->getPoint(m_points[1].index)->u); ccGL::Vertex3v(glFunc, m_points[2].cloud->getPoint(m_points[2].index)->u); glFunc->glEnd(); glFunc->glPopAttrib(); loop = true; } case 2: { //segment width glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(c_sizeFactor * context.renderZoom); //we draw the segments if (isSelected()) ccGL::Color3v(glFunc, ccColor::red.rgba); else ccGL::Color3v(glFunc, ccColor::green.rgba); glFunc->glBegin(GL_LINES); for (unsigned i=0; i<count; i++) { if (i+1<count || loop) { ccGL::Vertex3v(glFunc, m_points[i].cloud->getPoint(m_points[i].index)->u); ccGL::Vertex3v(glFunc, m_points[(i+1)%count].cloud->getPoint(m_points[(i+1)%count].index)->u); } } glFunc->glEnd(); glFunc->glPopAttrib(); } case 1: { //display point marker as spheres { if (!c_unitPointMarker) { c_unitPointMarker = QSharedPointer<ccSphere>(new ccSphere(1.0f, 0, "PointMarker", 12)); c_unitPointMarker->showColors(true); c_unitPointMarker->setVisible(true); c_unitPointMarker->setEnabled(true); } //build-up point maker own 'context' CC_DRAW_CONTEXT markerContext = context; markerContext.drawingFlags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! markerContext.display = 0; if (isSelected() && !pushName) c_unitPointMarker->setTempColor(ccColor::red); else c_unitPointMarker->setTempColor(context.labelDefaultMarkerCol); const ccViewportParameters& viewPortParams = context.display->getViewportParameters(); ccGLCameraParameters camera; context.display->getGLCameraParameters(camera); for (unsigned i = 0; i<count; i++) { glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); const CCVector3* P = m_points[i].cloud->getPoint(m_points[i].index); ccGL::Translate(glFunc, P->x, P->y, P->z); float scale = context.labelMarkerSize * m_relMarkerScale; if (viewPortParams.perspectiveView && viewPortParams.zFar > 0) { //in perspective view, the actual scale depends on the distance to the camera! const double* M = camera.modelViewMat.data(); double d = (camera.modelViewMat * CCVector3d::fromArray(P->u)).norm(); double unitD = viewPortParams.zFar / 2; //we consider that the 'standard' scale is at half the depth scale = static_cast<float>(scale * sqrt(d / unitD)); //sqrt = empirical (probably because the marker size is already partly compensated by ccGLWindow::computeActualPixelSize()) } glFunc->glScalef(scale, scale, scale); c_unitPointMarker->draw(markerContext); glFunc->glPopMatrix(); } } if (m_dispIn3D && !pushName) //no need to display label in point picking mode { QFont font(context.display->getTextDisplayFont()); //takes rendering zoom into account! //font.setPointSize(font.pointSize()+2); font.setBold(true); static const QChar ABC[3] = {'A','B','C'}; //we can't use the context 'ccGLCameraParameters' (viewport, modelView matrix, etc. ) //because it doesn't take the temporary 'GL transformation' into account! ccGLCameraParameters camera; //context.display->getGLCameraParameters(camera); glFunc->glGetIntegerv(GL_VIEWPORT, camera.viewport); glFunc->glGetDoublev(GL_PROJECTION_MATRIX, camera.projectionMat.data()); glFunc->glGetDoublev(GL_MODELVIEW_MATRIX, camera.modelViewMat.data()); //draw their name glFunc->glPushAttrib(GL_DEPTH_BUFFER_BIT); glFunc->glDisable(GL_DEPTH_TEST); for (unsigned j=0; j<count; j++) { const CCVector3* P = m_points[j].cloud->getPoint(m_points[j].index); QString title; if (count == 1) title = getName(); //for single-point labels we prefer the name else if (count == 3) title = ABC[j]; //for triangle-labels, we only display "A","B","C" else title = QString("P#%0").arg(m_points[j].index); //project it in 2D screen coordinates CCVector3d Q2D; camera.project(*P, Q2D); context.display->displayText( title, static_cast<int>(Q2D.x) + context.labelMarkerTextShift_pix, static_cast<int>(Q2D.y) + context.labelMarkerTextShift_pix, ccGenericGLDisplay::ALIGN_DEFAULT, context.labelOpacity / 100.0f, ccColor::white.rgba, &font ); } glFunc->glPopAttrib(); } } } if (pushName) { glFunc->glPopName(); } }
void ccSNECloud::drawMeOnly(CC_DRAW_CONTEXT& context) { if (!MACRO_Foreground(context)) //2D foreground only return; //do nothing //draw point cloud ccPointCloud::drawMeOnly(context); //draw normal vectors if (MACRO_Draw3D(context)) { if (size() == 0) //no points -> bail! return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); if (glFunc == nullptr) { assert(false); return; } //glDrawParams glParams; //getDrawingParameters(glParams); //get camera info ccGLCameraParameters camera; glFunc->glGetIntegerv(GL_VIEWPORT, camera.viewport); glFunc->glGetDoublev(GL_PROJECTION_MATRIX, camera.projectionMat.data()); glFunc->glGetDoublev(GL_MODELVIEW_MATRIX, camera.modelViewMat.data()); const ccViewportParameters& viewportParams = context.display->getViewportParameters(); //get point size for drawing float pSize; glFunc->glGetFloatv(GL_POINT_SIZE, &pSize); //draw normal vectors if highlighted //if ((m_isHighlighted | m_isAlternate | m_isActive)) //{ //setup if (pSize != 0) { glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(static_cast<GLfloat>(pSize)); } glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glEnable(GL_BLEND); //get normal vector properties int thickID = getScalarFieldIndexByName("Thickness"); //int weightID = getScalarFieldIndexByName("Weight"); //float weight; //float maxWeight = getScalarField( weightID )->getMax(); //draw normals glFunc->glBegin(GL_LINES); for (unsigned p = 0; p < size(); p++) { //get weight //weight = getScalarField(weightID)->getValue(p); //weight /= maxWeight; //push colour const ccColor::Rgb* col = m_currentDisplayedScalarField->getColor(m_currentDisplayedScalarField->getValue(p)); const ccColor::Rgba col4(col->r, col->g, col->b,200); glFunc->glColor4ubv(col4.rgba); //get length from thickness (if defined) float length = 1.0; if (thickID != -1) { length = getScalarField(thickID)->getValue(p); } //calculate start and end points of normal vector const CCVector3 start = *getPoint(p); CCVector3 end = start + (getPointNormal(p)*length); //push line to opengl ccGL::Vertex3v(glFunc, start.u); ccGL::Vertex3v(glFunc, end.u); } glFunc->glEnd(); //cleanup if (pSize != 0) { glFunc->glPopAttrib(); } glFunc->glPopMatrix(); } }
void ccPolyline::drawMeOnly(CC_DRAW_CONTEXT& context) { unsigned vertCount = size(); if (vertCount < 2) return; bool draw = false; if (MACRO_Draw3D(context)) { draw = !m_mode2D; } else if (m_mode2D) { bool drawFG = MACRO_Foreground(context); draw = ((drawFG && m_foreground) || (!drawFG && !m_foreground)); } if (!draw) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glFunc->glPushName(getUniqueIDForDisplay()); if (isColorOverriden()) ccGL::Color3v(glFunc, m_tempColor.rgb); else if (colorsShown()) ccGL::Color3v(glFunc, m_rgbColor.rgb); //display polyline if (vertCount > 1) { if (m_width != 0) { glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(static_cast<GLfloat>(m_width)); } //DGM: we do the 'GL_LINE_LOOP' manually as I have a strange bug //on one on my graphic card with this mode! //glBegin(m_isClosed ? GL_LINE_LOOP : GL_LINE_STRIP); glFunc->glBegin(GL_LINE_STRIP); for (unsigned i = 0; i < vertCount; ++i) { ccGL::Vertex3v(glFunc, getPoint(i)->u); } if (m_isClosed) { ccGL::Vertex3v(glFunc, getPoint(0)->u); } glFunc->glEnd(); //display arrow if (m_showArrow && m_arrowIndex < vertCount && (m_arrowIndex > 0 || m_isClosed)) { const CCVector3* P0 = getPoint(m_arrowIndex == 0 ? vertCount - 1 : m_arrowIndex - 1); const CCVector3* P1 = getPoint(m_arrowIndex); //direction of the last polyline chunk CCVector3 u = *P1 - *P0; u.normalize(); if (m_mode2D) { u *= -m_arrowLength; static const PointCoordinateType s_defaultArrowAngle = static_cast<PointCoordinateType>(15.0 * CC_DEG_TO_RAD); static const PointCoordinateType cost = cos(s_defaultArrowAngle); static const PointCoordinateType sint = sin(s_defaultArrowAngle); CCVector3 A(cost * u.x - sint * u.y, sint * u.x + cost * u.y, 0); CCVector3 B(cost * u.x + sint * u.y, -sint * u.x + cost * u.y, 0); glFunc->glBegin(GL_POLYGON); ccGL::Vertex3v(glFunc, (A + *P1).u); ccGL::Vertex3v(glFunc, (B + *P1).u); ccGL::Vertex3v(glFunc, (*P1).u); glFunc->glEnd(); } else { if (!c_unitArrow) { c_unitArrow = QSharedPointer<ccCone>(new ccCone(0.5, 0.0, 1.0)); c_unitArrow->showColors(true); c_unitArrow->showNormals(false); c_unitArrow->setVisible(true); c_unitArrow->setEnabled(true); } if (colorsShown()) c_unitArrow->setTempColor(m_rgbColor); else c_unitArrow->setTempColor(context.pointsDefaultCol); //build-up unit arrow own 'context' CC_DRAW_CONTEXT markerContext = context; markerContext.drawingFlags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! markerContext.display = 0; glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); ccGL::Translate(glFunc, P1->x, P1->y, P1->z); ccGLMatrix rotMat = ccGLMatrix::FromToRotation(u, CCVector3(0, 0, PC_ONE)); glFunc->glMultMatrixf(rotMat.inverse().data()); glFunc->glScalef(m_arrowLength, m_arrowLength, m_arrowLength); ccGL::Translate(glFunc, 0.0, 0.0, -0.5); c_unitArrow->draw(markerContext); glFunc->glPopMatrix(); } } if (m_width != 0) { glFunc->glPopAttrib(); } } //display vertices if (m_showVertices) { glFunc->glPushAttrib(GL_POINT_BIT); glFunc->glPointSize((GLfloat)m_vertMarkWidth); glFunc->glBegin(GL_POINTS); for (unsigned i = 0; i < vertCount; ++i) { ccGL::Vertex3v(glFunc, getPoint(i)->u); } glFunc->glEnd(); glFunc->glPopAttrib(); } if (pushName) glFunc->glPopName(); }
//override draw function void ccMouseCircle::draw(CC_DRAW_CONTEXT& context) { //only draw when visible if (!ccMouseCircle::isVisible()) return; //only draw in 2D foreground mode if (!MACRO_Foreground(context) || !MACRO_Draw2D(context)) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; //test viewport parameters const ccViewportParameters& params = context.display->getViewportParameters(); glFunc->glPushAttrib(GL_LINE_BIT); float relativeZoom = 1.0f; float dx = 0.0f; float dy = 0.0f; if (!m_params.perspectiveView) //ortho mode { //Screen pan & pivot compensation float totalZoom = m_params.zoom / m_params.pixelSize; m_winTotalZoom = params.zoom / params.pixelSize; relativeZoom = m_winTotalZoom / totalZoom; CCVector3d dC = m_params.cameraCenter - params.cameraCenter; CCVector3d P = m_params.pivotPoint - params.pivotPoint; m_params.viewMat.apply(P); static_cast<float>(dC.x + P.x); static_cast<float>(dC.y + P.y); dx *= m_winTotalZoom; dy *= m_winTotalZoom; } //thick dotted line glFunc->glLineWidth(2); glFunc->glLineStipple(1, 0xAAAA); glFunc->glEnable(GL_LINE_STIPPLE); const unsigned char* defaultColor = m_selected ? ccColor::red.rgba : context.textDefaultCol.rgb; glFunc->glColor3ubv(ccColor::red.rgba); //get height & width int halfW = static_cast<int>(context.glW / 2.0f); int halfH = static_cast<int>(context.glH / 2.0f); //get mouse position QPoint p = m_owner->asWidget()->mapFromGlobal(QCursor::pos()); int mx = p.x(); //mouse x-coord int my = 2*halfH - p.y(); //mouse y-coord in OpenGL coordinates (origin at bottom left, not top left) //calculate circle location int cx = dx+mx-halfW; int cy = dy+my-halfH; //draw circle glFunc->glBegin(GL_LINE_LOOP); for (int n = 0; n < ccMouseCircle::RESOLUTION; n++) { glFunc->glVertex2f(ccMouseCircle::UNIT_CIRCLE[n][0] * ccMouseCircle::RADIUS + cx, ccMouseCircle::UNIT_CIRCLE[n][1] * ccMouseCircle::RADIUS + cy); } glFunc->glEnd(); glFunc->glPopAttrib(); }
void ccGLUtils::DisplayTexture2DPosition(GLuint texID, int x, int y, int w, int h, unsigned char alpha/*=255*/) { QOpenGLContext* context = QOpenGLContext::currentContext(); if (!context) { assert(false); return; } QOpenGLFunctions_2_1* glFunc = context->versionFunctions<QOpenGLFunctions_2_1>(); if (glFunc) { glFunc->glBindTexture(GL_TEXTURE_2D, texID); glFunc->glPushAttrib(GL_ENABLE_BIT); glFunc->glEnable(GL_TEXTURE_2D); glFunc->glColor4ub(255, 255, 255, alpha); glFunc->glBegin(GL_QUADS); glFunc->glTexCoord2f(0.0, 1.0); glFunc->glVertex2i(x, y + h); glFunc->glTexCoord2f(0.0, 0.0); glFunc->glVertex2i(x, y); glFunc->glTexCoord2f(1.0, 0.0); glFunc->glVertex2i(x + w, y); glFunc->glTexCoord2f(1.0, 1.0); glFunc->glVertex2i(x + w, y + h); glFunc->glEnd(); glFunc->glBindTexture(GL_TEXTURE_2D, 0); glFunc->glPopAttrib(); glFunc->glBindTexture(GL_TEXTURE_2D, 0); } }
void ccSample::drawMeOnly(CC_DRAW_CONTEXT& context) { if (MACRO_Draw3D(context)) { if (!this->getSample()) return; QOpenGLFunctions_2_1* glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); bool pushName = MACRO_DrawEntityNames(context); if (pushName) { // not particularily fast if (MACRO_DrawFastNamesOnly(context)) return; glFunc->glPushName(getUniqueIDForDisplay()); } if (!c_unitPointMarker) { c_unitPointMarker = QSharedPointer<ccSphere>(new ccSphere(m_radius_, 0, "PointMarker", 12)); c_unitPointMarker->showColors(true); c_unitPointMarker->setVisible(true); c_unitPointMarker->setEnabled(true); } // build-up point maker own 'context' CC_DRAW_CONTEXT markerContext = context; markerContext.drawingFlags &= (~CC_DRAW_ENTITY_NAMES); // we must remove the 'push name flag' so // that the sphere doesn't push its own! markerContext.display = nullptr; if (isSelected() && !pushName) { c_unitPointMarker->setTempColor(ccColor::red); c_unitPointMarker->setRadius(2 * m_radius_); } else { c_unitPointMarker->setTempColor(ccColor::magenta); c_unitPointMarker->setRadius(m_radius_); } glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); float x, y, z; Eigen::Vector3f p = this->getSample()->getPosition(); // const CCVector3* P = m_points[i].cloud->getPoint(m_points[i].index); // ccGL::Translate(); glFunc->glTranslatef(p(0), p(1), p(2)); glFunc->glScalef(context.labelMarkerSize, context.labelMarkerSize, context.labelMarkerSize); m_current_scaling_ = context.labelMarkerSize; c_unitPointMarker->draw(markerContext); glFunc->glPopMatrix(); drawStratPos(context); if (pushName) glFunc->glPopName(); } }
void ccIndexedTransformationBuffer::drawMeOnly(CC_DRAW_CONTEXT& context) { //no picking enabled on trans. buffers if (MACRO_DrawEntityNames(context)) return; //only in 3D if (!MACRO_Draw3D(context)) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; size_t count = size(); //show path { ccGL::Color3v(glFunc, ccColor::green.rgba); glFunc->glBegin(count > 1 && m_showAsPolyline ? GL_LINE_STRIP : GL_POINTS); //show path as a polyline or points? for (ccIndexedTransformationBuffer::const_iterator it=begin(); it!=end(); ++it) glFunc->glVertex3fv(it->getTranslation()); glFunc->glEnd(); } //show trihedrons? if (m_showTrihedrons) { for (ccIndexedTransformationBuffer::const_iterator it=begin(); it!=end(); ++it) { glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glMultMatrixf(it->data()); //force line width glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(2.0f); glFunc->glBegin(GL_LINES); glFunc->glColor3f(1.0f,0.0f,0.0f); glFunc->glVertex3f(0.0f,0.0f,0.0f); glFunc->glVertex3f(m_trihedronsScale,0.0f,0.0f); glFunc->glColor3f(0.0f,1.0f,0.0f); glFunc->glVertex3f(0.0f,0.0f,0.0f); glFunc->glVertex3f(0.0f,m_trihedronsScale,0.0f); glFunc->glColor3f(0.0f,0.7f,1.0f); glFunc->glVertex3f(0.0f,0.0f,0.0f); glFunc->glVertex3f(0.0f,0.0f,m_trihedronsScale); glFunc->glEnd(); glFunc->glPopAttrib(); //GL_LINE_BIT glFunc->glPopMatrix(); } } }
void ccRenderingTools::DrawColorRamp(const CC_DRAW_CONTEXT& context, const ccScalarField* sf, ccGLWindow* win, int glW, int glH, float renderZoom/*=1.0f*/) { if (!sf || !sf->getColorScale() || !win) { return; } //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr); if (glFunc == nullptr) return; bool logScale = sf->logScale(); bool symmetricalScale = sf->symmetricalScale(); bool alwaysShowZero = sf->isZeroAlwaysShown(); //set of particular values //DGM: we work with doubles for maximum accuracy ccColorScale::LabelSet keyValues; bool customLabels = false; try { ccColorScale::Shared colorScale = sf->getColorScale(); if (colorScale && colorScale->customLabels().size() >= 2) { keyValues = colorScale->customLabels(); if (alwaysShowZero) { keyValues.insert(0.0); } customLabels = true; } else if (!logScale) { keyValues.insert(sf->displayRange().min()); keyValues.insert(sf->displayRange().start()); keyValues.insert(sf->displayRange().stop()); keyValues.insert(sf->displayRange().max()); keyValues.insert(sf->saturationRange().min()); keyValues.insert(sf->saturationRange().start()); keyValues.insert(sf->saturationRange().stop()); keyValues.insert(sf->saturationRange().max()); if (symmetricalScale) keyValues.insert(-sf->saturationRange().max()); if (alwaysShowZero) keyValues.insert(0.0); } else { ScalarType minDisp = sf->displayRange().min(); ScalarType maxDisp = sf->displayRange().max(); ConvertToLogScale(minDisp, maxDisp); keyValues.insert(minDisp); keyValues.insert(maxDisp); ScalarType startDisp = sf->displayRange().start(); ScalarType stopDisp = sf->displayRange().stop(); ConvertToLogScale(startDisp, stopDisp); keyValues.insert(startDisp); keyValues.insert(stopDisp); keyValues.insert(sf->saturationRange().min()); keyValues.insert(sf->saturationRange().start()); keyValues.insert(sf->saturationRange().stop()); keyValues.insert(sf->saturationRange().max()); } } catch (const std::bad_alloc&) { //not enough memory return; } //magic fix (for infinite values!) { for (ccColorScale::LabelSet::iterator it = keyValues.begin(); it != keyValues.end(); ++it) { #if defined(CC_WINDOWS) && defined(_MSC_VER) if (!_finite(*it)) #else if (!std::isfinite(*it)) #endif { bool minusInf = (*it < 0); keyValues.erase(it); if (minusInf) keyValues.insert(-std::numeric_limits<ScalarType>::max()); else keyValues.insert(std::numeric_limits<ScalarType>::max()); it = keyValues.begin(); //restart the process (easier than trying to be intelligent here ;) } } } //Internally, the elements in a set are already sorted //std::sort(keyValues.begin(), keyValues.end()); if (!customLabels && !sf->areNaNValuesShownInGrey()) { //remove 'hidden' values if (!logScale) { for (ccColorScale::LabelSet::iterator it = keyValues.begin(); it != keyValues.end(); ) { if (!sf->displayRange().isInRange(static_cast<ScalarType>(*it)) && (!alwaysShowZero || *it != 0)) //we keep zero if the user has explicitely asked for it! { ccColorScale::LabelSet::iterator toDelete = it; ++it; keyValues.erase(toDelete); } else { ++it; } } } else { //convert actual display range to log scale //(we can't do the opposite, otherwise we get accuracy/round-off issues!) ScalarType dispMin = sf->displayRange().start(); ScalarType dispMax = sf->displayRange().stop(); ConvertToLogScale(dispMin, dispMax); for (ccColorScale::LabelSet::iterator it = keyValues.begin(); it != keyValues.end(); ) { if (*it >= dispMin && *it <= dispMax) { ++it; } else { ccColorScale::LabelSet::iterator toDelete = it; ++it; keyValues.erase(toDelete); } } } } const ccGui::ParamStruct& displayParams = win->getDisplayParameters(); //default color: text color const ccColor::Rgbub& textColor = displayParams.textDefaultCol; //histogram? const ccScalarField::Histogram histogram = sf->getHistogram(); bool showHistogram = (displayParams.colorScaleShowHistogram && !logScale && histogram.maxValue != 0 && histogram.size() > 1); //display area QFont font = win->getTextDisplayFont(); //takes rendering zoom into account! const int strHeight = static_cast<int>(displayParams.defaultFontSize * renderZoom); //QFontMetrics(font).height() --> always returns the same value?! const int scaleWidth = static_cast<int>(displayParams.colorScaleRampWidth * renderZoom); const int scaleMaxHeight = (keyValues.size() > 1 ? std::max(glH - static_cast<int>(140 * renderZoom), 2 * strHeight) : scaleWidth); //if 1 value --> we draw a cube //centered orthoprojective view (-halfW,-halfH,halfW,halfH) int halfW = (glW >> 1); int halfH = (glH >> 1); //top-right corner of the scale ramp const int xShift = static_cast<int>(20 * renderZoom) + (showHistogram ? scaleWidth / 2 : 0); const int yShift = halfH - scaleMaxHeight / 2 - static_cast<int>(10 * renderZoom); glFunc->glPushAttrib(GL_DEPTH_BUFFER_BIT); glFunc->glDisable(GL_DEPTH_TEST); std::vector<double> sortedKeyValues(keyValues.begin(),keyValues.end()); double maxRange = sortedKeyValues.back()-sortedKeyValues.front(); //display color ramp { glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(renderZoom); //(x,y): current display area coordinates (top-left corner) int x = halfW-xShift-scaleWidth; int y = halfH-yShift-scaleMaxHeight; if (keyValues.size() > 1) { int histoStart = x + scaleWidth + std::min(std::max(scaleWidth / 8, 3), static_cast<int>(15 * renderZoom)); glFunc->glBegin(GL_LINES); for (int j=0; j<scaleMaxHeight; ++j) { double baseValue = sortedKeyValues.front() + (j * maxRange) / scaleMaxHeight; double value = baseValue; if (logScale) { value = exp(value*c_log10); } const ColorCompType* col = sf->getColor(static_cast<ScalarType>(value)); if (!col) { //special case: if we have user-defined labels, we want all the labels to be displayed with their associated color if (customLabels) { assert(sf->getColorScale() && !sf->getColorScale()->isRelative()); col = sf->getColorScale()->getColorByValue(value, ccColor::lightGrey.rgba); } else { col = ccColor::lightGrey.rgba; } } assert(col); glFunc->glColor3ubv(col); glFunc->glVertex2i(x,y+j); glFunc->glVertex2i(x+scaleWidth,y+j); if (showHistogram) { double bind = (value - sf->displayRange().min())*(histogram.size() - 1) / sf->displayRange().maxRange(); int bin = static_cast<int>(floor(bind)); double hVal = 0.0; if (bin >= 0 && bin < static_cast<int>(histogram.size())) //in symmetrical case we can get values outside of the real SF range { hVal = histogram[bin]; if (bin+1 < static_cast<int>(histogram.size())) { //linear interpolation double alpha = bind-static_cast<double>(bin); hVal = (1.0-alpha) * hVal + alpha * histogram[bin+1]; } } int xSpan = std::max(static_cast<int>(hVal / histogram.maxValue * (scaleWidth/2)),1); glFunc->glVertex2i(histoStart,y+j); glFunc->glVertex2i(histoStart+xSpan,y+j); } } glFunc->glEnd(); } else { //if there's a unique (visible) scalar value, we only draw a square! double value = sortedKeyValues.front(); if (logScale) value = exp(value*c_log10); const ColorCompType* col = sf->getColor(static_cast<ScalarType>(value)); glFunc->glColor3ubv(col ? col : ccColor::lightGrey.rgba); glFunc->glBegin(GL_POLYGON); glFunc->glVertex2i(x,y); glFunc->glVertex2i(x+scaleWidth,y); glFunc->glVertex2i(x+scaleWidth,y+scaleMaxHeight-1); glFunc->glVertex2i(x,y+scaleMaxHeight-1); glFunc->glEnd(); } //scale border const ccColor::Rgbub& lineColor = textColor; glFunc->glColor3ubv(lineColor.rgb); glFunc->glLineWidth(2.0f * renderZoom); glFunc->glEnable(GL_LINE_SMOOTH); glFunc->glBegin(GL_LINE_LOOP); glFunc->glVertex2i(x,y); glFunc->glVertex2i(x+scaleWidth,y); glFunc->glVertex2i(x+scaleWidth,y+scaleMaxHeight); glFunc->glVertex2i(x,y+scaleMaxHeight); glFunc->glEnd(); glFunc->glPopAttrib(); } //display labels { //list of labels to draw vlabelSet drawnLabels; //add first label drawnLabels.push_back(vlabel(0, 0, strHeight, sortedKeyValues.front())); if (keyValues.size() > 1) { //add last label drawnLabels.push_back(vlabel(scaleMaxHeight, scaleMaxHeight - strHeight, scaleMaxHeight, sortedKeyValues.back())); } //we try to display the other keyPoints (if any) if (keyValues.size() > 2) { assert(maxRange > 0.0); const int minGap = strHeight; for (size_t i=1; i<keyValues.size()-1; ++i) { int yScale = static_cast<int>((sortedKeyValues[i]-sortedKeyValues[0]) * scaleMaxHeight / maxRange); vlabelPair nLabels = GetVLabelsAround(yScale,drawnLabels); assert(nLabels.first != drawnLabels.end() && nLabels.second != drawnLabels.end()); if ( (nLabels.first == drawnLabels.end() || nLabels.first->yMax <= yScale - minGap) && (nLabels.second == drawnLabels.end() || nLabels.second->yMin >= yScale + minGap)) { //insert it at the right place (so as to keep a sorted list!) drawnLabels.insert(nLabels.second,vlabel(yScale,yScale-strHeight/2,yScale+strHeight/2,sortedKeyValues[i])); } } } //now we recursively display labels for which we have some room left if (!customLabels && drawnLabels.size() > 1) { const int minGap = strHeight*2; size_t drawnLabelsBefore = 0; //just to init the loop size_t drawnLabelsAfter = drawnLabels.size(); //proceed until no more label can be inserted while (drawnLabelsAfter > drawnLabelsBefore) { drawnLabelsBefore = drawnLabelsAfter; vlabelSet::iterator it1 = drawnLabels.begin(); vlabelSet::iterator it2 = it1; ++it2; for (; it2 != drawnLabels.end(); ++it2) { if (it1->yMax + 2*minGap < it2->yMin) { //insert label double val = (it1->val + it2->val)/2.0; int yScale = static_cast<int>((val-sortedKeyValues[0]) * scaleMaxHeight / maxRange); //insert it at the right place (so as to keep a sorted list!) drawnLabels.insert(it2,vlabel(yScale,yScale-strHeight/2,yScale+strHeight/2,val)); } it1 = it2; } drawnLabelsAfter = drawnLabels.size(); } } //display labels //Some versions of Qt seem to need glColorf instead of glColorub! (see https://bugreports.qt-project.org/browse/QTBUG-6217) glFunc->glColor3f(textColor.r / 255.0f, textColor.g / 255.0f, textColor.b / 255.0f); //Scalar field name const char* sfName = sf->getName(); if (sfName) { //QString sfTitle = QString("[%1]").arg(sfName); QString sfTitle(sfName); if (sf->getGlobalShift() != 0) sfTitle += QString("[Shifted]"); if (logScale) sfTitle += QString("[Log scale]"); //we leave some (vertical) space for the top-most label! win->displayText(sfTitle, glW-xShift, glH-yShift+strHeight, ccGLWindow::ALIGN_HRIGHT | ccGLWindow::ALIGN_VTOP, 0, 0, &font); } //precision (same as color scale) const unsigned precision = displayParams.displayedNumPrecision; //format const char format = (sf->logScale() ? 'E' : 'f'); //tick const int tickSize = static_cast<int>(4 * renderZoom); //for labels const int x = glW-xShift-scaleWidth-2*tickSize-1; const int y = glH-yShift-scaleMaxHeight; //for ticks const int xTick = halfW-xShift-scaleWidth-tickSize-1; const int yTick = halfH-yShift-scaleMaxHeight; for (vlabelSet::iterator it = drawnLabels.begin(); it != drawnLabels.end(); ++it) { vlabelSet::iterator itNext = it; ++itNext; //position unsigned char align = ccGLWindow::ALIGN_HRIGHT; if (it == drawnLabels.begin()) align |= ccGLWindow::ALIGN_VTOP; else if (itNext == drawnLabels.end()) align |= ccGLWindow::ALIGN_VBOTTOM; else align |= ccGLWindow::ALIGN_VMIDDLE; double value = it->val; if (logScale) value = exp(value*c_log10); win->displayText(QString::number(value,format,precision), x, y+it->yPos, align, 0, 0, &font); glFunc->glBegin(GL_LINES); glFunc->glVertex2i(xTick,yTick+it->yPos); glFunc->glVertex2i(xTick+tickSize,yTick+it->yPos); glFunc->glEnd(); } } glFunc->glPopAttrib(); }
void ccClipBox::drawMeOnly(CC_DRAW_CONTEXT& context) { if (!MACRO_Draw3D(context)) return; if (!m_box.isValid()) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; if (m_showBox) { //m_box.draw(m_selected ? context.bbDefaultCol : ccColor::magenta); m_box.draw(context, ccColor::yellow); } if (!m_selected) { //nothing to show return; } //standard case: list names pushing (1st level) bool pushName = MACRO_DrawEntityNames(context); if (pushName) { glFunc->glPushName(getUniqueIDForDisplay()); } //draw the interactors { const CCVector3& minC = m_box.minCorner(); const CCVector3& maxC = m_box.maxCorner(); const CCVector3 center = m_box.getCenter(); PointCoordinateType scale = computeArrowsScale(); //custom arrow 'context' CC_DRAW_CONTEXT componentContext = context; componentContext.drawingFlags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the arows don't push their own! componentContext.display = 0; if (pushName) //2nd level = sub-item { glFunc->glPushName(0); //fake ID, will be replaced by the arrows one if any } DrawUnitArrow(X_MINUS_ARROW*pushName, CCVector3(minC.x, center.y, center.z), CCVector3(-1.0, 0.0, 0.0), scale, ccColor::red, componentContext); DrawUnitArrow(X_PLUS_ARROW*pushName, CCVector3(maxC.x, center.y, center.z), CCVector3(1.0, 0.0, 0.0), scale, ccColor::red, componentContext); DrawUnitArrow(Y_MINUS_ARROW*pushName, CCVector3(center.x, minC.y, center.z), CCVector3(0.0, -1.0, 0.0), scale, ccColor::green, componentContext); DrawUnitArrow(Y_PLUS_ARROW*pushName, CCVector3(center.x, maxC.y, center.z), CCVector3(0.0, 1.0, 0.0), scale, ccColor::green, componentContext); DrawUnitArrow(Z_MINUS_ARROW*pushName, CCVector3(center.x, center.y, minC.z), CCVector3(0.0, 0.0, -1.0), scale, ccColor::blue, componentContext); DrawUnitArrow(Z_PLUS_ARROW*pushName, CCVector3(center.x, center.y, maxC.z), CCVector3(0.0, 0.0, 1.0), scale, ccColor::blue, componentContext); DrawUnitCross(CROSS*pushName, minC - CCVector3(scale, scale, scale) / 2.0, scale, ccColor::yellow, componentContext); //DrawUnitSphere(SPHERE*pushName, maxC + CCVector3(scale, scale, scale) / 2.0, scale / 2.0, ccColor::yellow, componentContext); DrawUnitTorus(X_MINUS_TORUS*pushName, CCVector3(minC.x, center.y, center.z), CCVector3(-1.0, 0.0, 0.0), scale, c_lightRed, componentContext); DrawUnitTorus(Y_MINUS_TORUS*pushName, CCVector3(center.x, minC.y, center.z), CCVector3(0.0, -1.0, 0.0), scale, c_lightGreen, componentContext); DrawUnitTorus(Z_MINUS_TORUS*pushName, CCVector3(center.x, center.y, minC.z), CCVector3(0.0, 0.0, -1.0), scale, c_lightBlue, componentContext); DrawUnitTorus(X_PLUS_TORUS*pushName, CCVector3(maxC.x, center.y, center.z), CCVector3(1.0, 0.0, 0.0), scale, c_lightRed, componentContext); DrawUnitTorus(Y_PLUS_TORUS*pushName, CCVector3(center.x, maxC.y, center.z), CCVector3(0.0, 1.0, 0.0), scale, c_lightGreen, componentContext); DrawUnitTorus(Z_PLUS_TORUS*pushName, CCVector3(center.x, center.y, maxC.z), CCVector3(0.0, 0.0, 1.0), scale, c_lightBlue, componentContext); if (pushName) { glFunc->glPopName(); } } if (pushName) { glFunc->glPopName(); } }
void ccHObject::draw(CC_DRAW_CONTEXT& context) { if (!isEnabled()) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //are we currently drawing objects in 2D or 3D? bool draw3D = MACRO_Draw3D(context); //the entity must be either visible or selected, and of course it should be displayed in this context bool drawInThisContext = ((m_visible || m_selected) && m_currentDisplay == context.display); if (draw3D) { //apply 3D 'temporary' transformation (for display only) if (m_glTransEnabled) { glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glMultMatrixf(m_glTrans.data()); } //LOD for clouds is enabled? if ( context.decimateCloudOnMove && context.currentLODLevel > 0) { //only for real clouds drawInThisContext &= isA(CC_TYPES::POINT_CLOUD); } } //draw entity if (m_visible && drawInThisContext) { if (( !m_selected || !MACRO_SkipSelected(context) ) && ( m_selected || !MACRO_SkipUnselected(context) )) { //apply default color (in case of) ccGL::Color3v(glFunc, context.pointsDefaultCol.rgb); //enable clipping planes (if any) bool useClipPlanes = (draw3D && !m_clipPlanes.empty()); if (useClipPlanes) { toggleClipPlanes(context, true); } drawMeOnly(context); //disable clipping planes (if any) if (useClipPlanes) { toggleClipPlanes(context, false); } //draw name in 3D (we display it in the 2D foreground layer in fact!) if (m_showNameIn3D && MACRO_Draw2D(context) && MACRO_Foreground(context) && !MACRO_DrawEntityNames(context)) drawNameIn3D(context); } } //draw entity's children for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) (*it)->draw(context); //if the entity is currently selected, we draw its bounding-box if (m_selected && draw3D && drawInThisContext && !MACRO_DrawEntityNames(context) && context.currentLODLevel == 0) { drawBB(context, context.bbDefaultCol); } if (draw3D && m_glTransEnabled) glFunc->glPopMatrix(); }
void cc2DViewportLabel::drawMeOnly(CC_DRAW_CONTEXT& context) { //2D foreground only if (!MACRO_Foreground(context) || !MACRO_Draw2D(context)) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //test viewport parameters const ccViewportParameters& params = context.display->getViewportParameters(); //general parameters if ( params.perspectiveView != m_params.perspectiveView || params.objectCenteredView != m_params.objectCenteredView || params.pixelSize != m_params.pixelSize) { return; } //test base view matrix for (unsigned i = 0; i < 12; ++i) if (fabs(params.viewMat.data()[i] - m_params.viewMat.data()[i]) > ZERO_TOLERANCE) return; if (m_params.perspectiveView) { if (params.fov != m_params.fov || params.perspectiveAspectRatio != m_params.perspectiveAspectRatio) return; if ((params.pivotPoint - m_params.pivotPoint).norm() > ZERO_TOLERANCE || (params.cameraCenter - m_params.cameraCenter).norm() > ZERO_TOLERANCE) return; } else { if (params.orthoAspectRatio != m_params.orthoAspectRatio) return; } glFunc->glPushAttrib(GL_LINE_BIT); float relativeZoom = 1.0f; float dx = 0, dy = 0; if (!m_params.perspectiveView) //ortho mode { //Screen pan & pivot compensation float totalZoom = m_params.zoom / m_params.pixelSize; float winTotalZoom = params.zoom / params.pixelSize; relativeZoom = winTotalZoom / totalZoom; CCVector3d dC = m_params.cameraCenter - params.cameraCenter; CCVector3d P = m_params.pivotPoint - params.pivotPoint; m_params.viewMat.apply(P); dx = static_cast<float>(dC.x + P.x); dy = static_cast<float>(dC.y + P.y); dx *= winTotalZoom; dy *= winTotalZoom; } //thick dotted line glFunc->glLineWidth(2); glFunc->glLineStipple(1, 0xAAAA); glFunc->glEnable(GL_LINE_STIPPLE); const unsigned char* defaultColor = m_selected ? ccColor::red.rgba : context.textDefaultCol.rgb; glFunc->glColor3ubv(defaultColor); glFunc->glBegin(GL_LINE_LOOP); glFunc->glVertex2f(dx + m_roi[0] * relativeZoom, dy + m_roi[1] * relativeZoom); glFunc->glVertex2f(dx + m_roi[2] * relativeZoom, dy + m_roi[1] * relativeZoom); glFunc->glVertex2f(dx + m_roi[2] * relativeZoom, dy + m_roi[3] * relativeZoom); glFunc->glVertex2f(dx + m_roi[0] * relativeZoom, dy + m_roi[3] * relativeZoom); glFunc->glEnd(); glFunc->glPopAttrib(); //title QString title(getName()); if (!title.isEmpty()) { QFont titleFont(context.display->getTextDisplayFont()); //takes rendering zoom into account! titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); int titleHeight = titleFontMetrics.height(); int xStart = (int)(dx + 0.5f*(float)context.glW + std::min<float>(m_roi[0], m_roi[2])*relativeZoom); int yStart = (int)(dy + 0.5f*(float)context.glH + std::min<float>(m_roi[1], m_roi[3])*relativeZoom); context.display->displayText(title, xStart, yStart - 5 - titleHeight, ccGenericGLDisplay::ALIGN_DEFAULT, 0, defaultColor, &titleFont); } }