void ccOctree::drawMeOnly(CC_DRAW_CONTEXT& context) { if (m_thePointsAndTheirCellCodes.empty()) return; if (MACRO_Draw3D(context)) { bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not fast at all! if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); } assert(m_displayedLevel < 256); RenderOctreeAs(m_displayType,this,static_cast<uchar>(m_displayedLevel),m_theAssociatedCloudAsGPC,m_glListID,m_shouldBeRefreshed); if (m_shouldBeRefreshed) m_shouldBeRefreshed = false; if (pushName) 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 ccClipBox::drawMeOnly(CC_DRAW_CONTEXT& context) { if (!MACRO_Draw3D(context)) return; if (!m_box.isValid()) return; //m_box.draw(m_selected ? context.bbDefaultCol : ccColor::magenta); m_box.draw(ccColor::yellow); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueID()); if (m_selected) { //draw the interactors const CCVector3& minC = m_box.minCorner(); const CCVector3& maxC = m_box.maxCorner(); CCVector3 center = m_box.getCenter(); PointCoordinateType scale = computeArrowsScale(); //custom arrow 'context' CC_DRAW_CONTEXT componentContext = context; componentContext.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the arows don't push their own! componentContext._win = 0; //1 if names shall be pushed, 0 otherwise int pushMod = (pushName ? 1 : 0); if (pushName) 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) glPopName(); } if (pushName) glPopName(); }
void ccOctree::drawMeOnly(CC_DRAW_CONTEXT& context) { if (m_thePointsAndTheirCellCodes.empty()) return; if (MACRO_Draw3D(context)) { bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueID()); RenderOctreeAs(displayType,this,displayedLevel,_associatedCloud,glID,shouldBeRefreshed); if (shouldBeRefreshed) shouldBeRefreshed = false; if (pushName) glPopName(); } }
void ccKdTree::drawMeOnly(CC_DRAW_CONTEXT& context) { if (!m_associatedGenericCloud || !m_root) return; if (MACRO_Draw3D(context)) { bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not fast at all! if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); } DrawMeOnlyVisitor(m_associatedGenericCloud->getBB()).visit(m_root); if (pushName) glPopName(); } }
void ccGenericMesh::drawMeOnly(CC_DRAW_CONTEXT& context) { ccGenericPointCloud* vertices = getAssociatedCloud(); if (!vertices) return; handleColorRamp(context); //3D pass if (MACRO_Draw3D(context)) { //any triangle? unsigned triNum = size(); if (triNum == 0) return; //L.O.D. bool lodEnabled = (triNum > GET_MAX_LOD_FACES_NUMBER() && context.decimateMeshOnMove && MACRO_LODActivated(context)); unsigned decimStep = (lodEnabled ? (unsigned)ceil((float)triNum*3 / (float)GET_MAX_LOD_FACES_NUMBER()) : 1); unsigned displayedTriNum = triNum / decimStep; //display parameters glDrawParams glParams; getDrawingParameters(glParams); glParams.showNorms &= bool(MACRO_LightIsEnabled(context)); //vertices visibility const ccGenericPointCloud::VisibilityTableType* verticesVisibility = vertices->getTheVisibilityArray(); bool visFiltering = (verticesVisibility && verticesVisibility->isAllocated()); //wireframe ? (not compatible with LOD) bool showWired = isShownAsWire() && !lodEnabled; //per-triangle normals? bool showTriNormals = (hasTriNormals() && triNormsShown()); //fix 'showNorms' glParams.showNorms = showTriNormals || (vertices->hasNormals() && m_normalsDisplayed); //materials & textures bool applyMaterials = (hasMaterials() && materialsShown()); bool showTextures = (hasTextures() && materialsShown() && !lodEnabled); //GL name pushing bool pushName = MACRO_DrawEntityNames(context); //special case: triangle names pushing (for picking) bool pushTriangleNames = MACRO_DrawTriangleNames(context); pushName |= pushTriangleNames; if (pushName) { //not fast at all! if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); //minimal display for picking mode! glParams.showNorms = false; glParams.showColors = false; //glParams.showSF --> we keep it only if SF 'NaN' values are hidden showTriNormals = false; applyMaterials = false; showTextures = false; } //in the case we need to display scalar field colors ccScalarField* currentDisplayedScalarField = 0; bool greyForNanScalarValues = true; unsigned colorRampSteps = 0; ccColorScale::Shared colorScale(0); if (glParams.showSF) { assert(vertices->isA(CC_TYPES::POINT_CLOUD)); ccPointCloud* cloud = static_cast<ccPointCloud*>(vertices); greyForNanScalarValues = (cloud->getCurrentDisplayedScalarField() && cloud->getCurrentDisplayedScalarField()->areNaNValuesShownInGrey()); if (greyForNanScalarValues && pushName) { //in picking mode, no need to take SF into account if we don't hide any points! glParams.showSF = false; } else { currentDisplayedScalarField = cloud->getCurrentDisplayedScalarField(); colorScale = currentDisplayedScalarField->getColorScale(); colorRampSteps = currentDisplayedScalarField->getColorRampSteps(); assert(colorScale); //get default color ramp if cloud has no scale associated?! if (!colorScale) colorScale = ccColorScalesManager::GetUniqueInstance()->getDefaultScale(ccColorScalesManager::BGYR); } } //materials or color? bool colorMaterial = false; if (glParams.showSF || glParams.showColors) { applyMaterials = false; colorMaterial = true; glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); } //in the case we need to display vertex colors ColorsTableType* rgbColorsTable = 0; if (glParams.showColors) { if (isColorOverriden()) { glColor3ubv(m_tempColor); glParams.showColors = false; } else { assert(vertices->isA(CC_TYPES::POINT_CLOUD)); rgbColorsTable = static_cast<ccPointCloud*>(vertices)->rgbColors(); } } else { glColor3fv(context.defaultMat.diffuseFront); } if (glParams.showNorms) { //DGM: Strangely, when Qt::renderPixmap is called, the OpenGL version can fall to 1.0! glEnable((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2 ? GL_RESCALE_NORMAL : GL_NORMALIZE)); glEnable(GL_LIGHTING); context.defaultMat.applyGL(true,colorMaterial); } //in the case we need normals (i.e. lighting) NormsIndexesTableType* normalsIndexesTable = 0; ccNormalVectors* compressedNormals = 0; if (glParams.showNorms) { assert(vertices->isA(CC_TYPES::POINT_CLOUD)); normalsIndexesTable = static_cast<ccPointCloud*>(vertices)->normals(); compressedNormals = ccNormalVectors::GetUniqueInstance(); } //stipple mask if (stipplingEnabled()) EnableGLStippleMask(true); if (!pushTriangleNames && !visFiltering && !(applyMaterials || showTextures) && (!glParams.showSF || greyForNanScalarValues)) { //the GL type depends on the PointCoordinateType 'size' (float or double) GLenum GL_COORD_TYPE = sizeof(PointCoordinateType) == 4 ? GL_FLOAT : GL_DOUBLE; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3,GL_COORD_TYPE,0,GetVertexBuffer()); if (glParams.showNorms) { glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_COORD_TYPE,0,GetNormalsBuffer()); } if (glParams.showSF || glParams.showColors) { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3,GL_UNSIGNED_BYTE,0,GetColorsBuffer()); } //we can scan and process each chunk separately in an optimized way //we mimic the way ccMesh beahves by using virtual chunks! unsigned chunks = static_cast<unsigned>(ceil((double)displayedTriNum/(double)MAX_NUMBER_OF_ELEMENTS_PER_CHUNK)); unsigned chunkStart = 0; const colorType* col = 0; for (unsigned k=0; k<chunks; ++k, chunkStart += MAX_NUMBER_OF_ELEMENTS_PER_CHUNK) { //virtual chunk size const unsigned chunkSize = k+1 < chunks ? MAX_NUMBER_OF_ELEMENTS_PER_CHUNK : (displayedTriNum % MAX_NUMBER_OF_ELEMENTS_PER_CHUNK); //vertices PointCoordinateType* _vertices = GetVertexBuffer(); for (unsigned n=0; n<chunkSize; n+=decimStep) { const CCLib::TriangleSummitsIndexes* ti = getTriangleIndexes(chunkStart + n); memcpy(_vertices,vertices->getPoint(ti->i1)->u,sizeof(PointCoordinateType)*3); _vertices+=3; memcpy(_vertices,vertices->getPoint(ti->i2)->u,sizeof(PointCoordinateType)*3); _vertices+=3; memcpy(_vertices,vertices->getPoint(ti->i3)->u,sizeof(PointCoordinateType)*3); _vertices+=3; } //scalar field if (glParams.showSF) { colorType* _rgbColors = GetColorsBuffer(); assert(colorScale); for (unsigned n=0; n<chunkSize; n+=decimStep) { const CCLib::TriangleSummitsIndexes* ti = getTriangleIndexes(chunkStart + n); col = currentDisplayedScalarField->getValueColor(ti->i1); memcpy(_rgbColors,col,sizeof(colorType)*3); _rgbColors += 3; col = currentDisplayedScalarField->getValueColor(ti->i2); memcpy(_rgbColors,col,sizeof(colorType)*3); _rgbColors += 3; col = currentDisplayedScalarField->getValueColor(ti->i3); memcpy(_rgbColors,col,sizeof(colorType)*3); _rgbColors += 3; } } //colors else if (glParams.showColors) { colorType* _rgbColors = GetColorsBuffer(); for (unsigned n=0; n<chunkSize; n+=decimStep) { const CCLib::TriangleSummitsIndexes* ti = getTriangleIndexes(chunkStart + n); memcpy(_rgbColors,rgbColorsTable->getValue(ti->i1),sizeof(colorType)*3); _rgbColors += 3; memcpy(_rgbColors,rgbColorsTable->getValue(ti->i2),sizeof(colorType)*3); _rgbColors += 3; memcpy(_rgbColors,rgbColorsTable->getValue(ti->i3),sizeof(colorType)*3); _rgbColors += 3; } } //normals if (glParams.showNorms) { PointCoordinateType* _normals = GetNormalsBuffer(); if (showTriNormals) { for (unsigned n=0; n<chunkSize; n+=decimStep) { CCVector3 Na, Nb, Nc; getTriangleNormals(chunkStart + n, Na, Nb, Nc); memcpy(_normals,Na.u,sizeof(PointCoordinateType)*3); _normals+=3; memcpy(_normals,Nb.u,sizeof(PointCoordinateType)*3); _normals+=3; memcpy(_normals,Nc.u,sizeof(PointCoordinateType)*3); _normals+=3; } } else { for (unsigned n=0; n<chunkSize; n+=decimStep) { const CCLib::TriangleSummitsIndexes* ti = getTriangleIndexes(chunkStart + n); memcpy(_normals,vertices->getPointNormal(ti->i1).u,sizeof(PointCoordinateType)*3); _normals+=3; memcpy(_normals,vertices->getPointNormal(ti->i2).u,sizeof(PointCoordinateType)*3); _normals+=3; memcpy(_normals,vertices->getPointNormal(ti->i3).u,sizeof(PointCoordinateType)*3); _normals+=3; } } } if (!showWired) { glDrawArrays(lodEnabled ? GL_POINTS : GL_TRIANGLES,0,(chunkSize/decimStep)*3); } else { glDrawElements(GL_LINES,(chunkSize/decimStep)*6,GL_UNSIGNED_INT,GetWireVertexIndexes()); } } //disable arrays glDisableClientState(GL_VERTEX_ARRAY); if (glParams.showNorms) glDisableClientState(GL_NORMAL_ARRAY); if (glParams.showSF || glParams.showColors) glDisableClientState(GL_COLOR_ARRAY); } else { //current vertex color const colorType *col1=0,*col2=0,*col3=0; //current vertex normal const PointCoordinateType *N1=0,*N2=0,*N3=0; //current vertex texture coordinates float *Tx1=0,*Tx2=0,*Tx3=0; //loop on all triangles int lasMtlIndex = -1; if (showTextures) { //#define TEST_TEXTURED_BUNDLER_IMPORT #ifdef TEST_TEXTURED_BUNDLER_IMPORT glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(context.sourceBlend, context.destBlend); #endif glEnable(GL_TEXTURE_2D); } if (pushTriangleNames) glPushName(0); GLenum triangleDisplayType = lodEnabled ? GL_POINTS : showWired ? GL_LINE_LOOP : GL_TRIANGLES; glBegin(triangleDisplayType); //per-triangle normals const NormsIndexesTableType* triNormals = getTriNormsTable(); //materials const ccMaterialSet* materials = getMaterialSet(); for (unsigned n=0; n<triNum; ++n) { //current triangle vertices const CCLib::TriangleSummitsIndexes* tsi = getTriangleIndexes(n); //LOD: shall we display this triangle? if (n % decimStep) continue; if (visFiltering) { //we skip the triangle if at least one vertex is hidden if ((verticesVisibility->getValue(tsi->i1) != POINT_VISIBLE) || (verticesVisibility->getValue(tsi->i2) != POINT_VISIBLE) || (verticesVisibility->getValue(tsi->i3) != POINT_VISIBLE)) continue; } if (glParams.showSF) { assert(colorScale); col1 = currentDisplayedScalarField->getValueColor(tsi->i1); if (!col1) continue; col2 = currentDisplayedScalarField->getValueColor(tsi->i2); if (!col2) continue; col3 = currentDisplayedScalarField->getValueColor(tsi->i3); if (!col3) continue; } else if (glParams.showColors) { col1 = rgbColorsTable->getValue(tsi->i1); col2 = rgbColorsTable->getValue(tsi->i2); col3 = rgbColorsTable->getValue(tsi->i3); } if (glParams.showNorms) { if (showTriNormals) { assert(triNormals); int n1,n2,n3; getTriangleNormalIndexes(n,n1,n2,n3); N1 = (n1>=0 ? ccNormalVectors::GetNormal(triNormals->getValue(n1)).u : 0); N2 = (n1==n2 ? N1 : n1>=0 ? ccNormalVectors::GetNormal(triNormals->getValue(n2)).u : 0); N3 = (n1==n3 ? N1 : n3>=0 ? ccNormalVectors::GetNormal(triNormals->getValue(n3)).u : 0); } else { N1 = compressedNormals->getNormal(normalsIndexesTable->getValue(tsi->i1)).u; N2 = compressedNormals->getNormal(normalsIndexesTable->getValue(tsi->i2)).u; N3 = compressedNormals->getNormal(normalsIndexesTable->getValue(tsi->i3)).u; } } if (applyMaterials || showTextures) { assert(materials); int newMatlIndex = this->getTriangleMtlIndex(n); //do we need to change material? if (lasMtlIndex != newMatlIndex) { assert(newMatlIndex<(int)materials->size()); glEnd(); if (showTextures) { GLuint texID = (newMatlIndex>=0 ? (*materials)[newMatlIndex].texID : 0); if (texID>0) assert(glIsTexture(texID)); glBindTexture(GL_TEXTURE_2D, texID); } //if we don't have any current material, we apply default one (newMatlIndex>=0 ? (*materials)[newMatlIndex] : context.defaultMat).applyGL(glParams.showNorms,false); glBegin(triangleDisplayType); lasMtlIndex=newMatlIndex; } if (showTextures) { getTriangleTexCoordinates(n,Tx1,Tx2,Tx3); } } if (pushTriangleNames) { glEnd(); glLoadName(n); glBegin(triangleDisplayType); } else if (showWired) { glEnd(); glBegin(triangleDisplayType); } //vertex 1 if (N1) ccGL::Normal3v(N1); if (col1) glColor3ubv(col1); if (Tx1) glTexCoord2fv(Tx1); ccGL::Vertex3v(vertices->getPoint(tsi->i1)->u); //vertex 2 if (N2) ccGL::Normal3v(N2); if (col2) glColor3ubv(col2); if (Tx2) glTexCoord2fv(Tx2); ccGL::Vertex3v(vertices->getPoint(tsi->i2)->u); //vertex 3 if (N3) ccGL::Normal3v(N3); if (col3) glColor3ubv(col3); if (Tx3) glTexCoord2fv(Tx3); ccGL::Vertex3v(vertices->getPoint(tsi->i3)->u); } glEnd(); if (pushTriangleNames) glPopName(); if (showTextures) { #ifdef TEST_TEXTURED_BUNDLER_IMPORT glPopAttrib(); //GL_COLOR_BUFFER_BIT #endif glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } } if (stipplingEnabled()) EnableGLStippleMask(false); if (colorMaterial) glDisable(GL_COLOR_MATERIAL); if (glParams.showNorms) { glDisable(GL_LIGHTING); glDisable((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2 ? GL_RESCALE_NORMAL : GL_NORMALIZE)); } if (pushName) glPopName(); } }
void ccSymbolCloud::drawMeOnly(CC_DRAW_CONTEXT& context) { if (!m_points->isAllocated()) return; //nothing to do?! if (!m_showSymbols && !m_showLabels) return; if (MACRO_Draw2D(context) && MACRO_Foreground(context)) { //we get display parameters glDrawParams glParams; getDrawingParameters(glParams); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); bool hasLabels = !m_labels.empty(); if (pushName) { //not fast at all! if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueID()); hasLabels = false; //no need to display labels in 'picking' mode } //we should already be in orthoprojective & centered omde //glOrtho(-halfW,halfW,-halfH,halfH,-maxS,maxS); //default color const unsigned char* color = context.pointsDefaultCol; if (isColorOverriden()) { color = m_tempColor; glParams.showColors = false; } if (!glParams.showColors) glColor3ubv(color); unsigned numberOfPoints = size(); //viewport parameters (will be used to project 3D positions to 2D) int VP[4]; context._win->getViewportArray(VP); const double* MM = context._win->getModelViewMatd(); //viewMat const double* MP = context._win->getProjectionMatd(); //projMat //only usefull when displaying labels! QFont font(context._win->getTextDisplayFont()); //takes rendering zoom into account! font.setPointSize(static_cast<int>(m_fontSize * context.renderZoom)); //font.setBold(true); QFontMetrics fontMetrics(font); double symbolSizeBackup = m_symbolSize; m_symbolSize *= static_cast<double>(context.renderZoom); double xpShift = 0.0; if (m_labelAlignFlags & ccGenericGLDisplay::ALIGN_HLEFT) xpShift = m_symbolSize/2.0; else if (m_labelAlignFlags & ccGenericGLDisplay::ALIGN_HRIGHT) xpShift = -m_symbolSize/2.0; double ypShift = 0.0; if (m_labelAlignFlags & ccGenericGLDisplay::ALIGN_VTOP) ypShift = m_symbolSize/2.0; else if (m_labelAlignFlags & ccGenericGLDisplay::ALIGN_VBOTTOM) ypShift = -m_symbolSize/2.0; //draw symbols + labels { for (unsigned i=0;i<numberOfPoints;i++) { //symbol center const CCVector3* P = getPoint(i); //project it in 2D screen coordinates GLdouble xp,yp,zp; gluProject(P->x,P->y,P->z,MM,MP,VP,&xp,&yp,&zp); //apply point color (if any) if (glParams.showColors) { color = getPointColor(i); glColor3ubv(color); } //draw associated symbol if (m_showSymbols && m_symbolSize > 0.0) { drawSymbolAt(xp-static_cast<double>(context.glW/2),yp-static_cast<double>(context.glH/2)); } //draw associated label? if (m_showLabels && hasLabels && m_labels.size() > i && !m_labels[i].isNull()) { //draw label context._win->displayText(m_labels[i],static_cast<int>(xp+xpShift),static_cast<int>(yp+ypShift),m_labelAlignFlags,0,color,&font); } } } //restore original symbol size m_symbolSize = symbolSizeBackup; if (pushName) glPopName(); } }
void ccPolyline::drawMeOnly(CC_DRAW_CONTEXT& context) { //no picking enabled on polylines if (MACRO_DrawPointNames(context)) return; 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) { //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueIDForDisplay()); if (colorsShown()) ccGL::Color3v(m_rgbColor.rgb); //display polyline if (vertCount > 1) { if (m_width != 0) { glPushAttrib(GL_LINE_BIT); 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); glBegin(GL_LINE_STRIP); for (unsigned i=0; i<vertCount; ++i) { ccGL::Vertex3v(getPoint(i)->u); } if (m_isClosed) { ccGL::Vertex3v(getPoint(0)->u); } 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); glBegin(GL_POLYGON); ccGL::Vertex3v((A+*P1).u); ccGL::Vertex3v((B+*P1).u); ccGL::Vertex3v(( *P1).u); 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.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! markerContext._win = 0; glMatrixMode(GL_MODELVIEW); glPushMatrix(); ccGL::Translate(P1->x,P1->y,P1->z); ccGLMatrix rotMat = ccGLMatrix::FromToRotation(CCVector3(0,0,1),u); glMultMatrixf(rotMat.inverse().data()); glScalef(m_arrowLength,m_arrowLength,m_arrowLength); ccGL::Translate(0.0,0.0,-0.5); c_unitArrow->draw(markerContext); glPopMatrix(); } } if (m_width != 0) { glPopAttrib(); } } //display vertices if (m_showVertices) { glPushAttrib(GL_POINT_BIT); glPointSize((GLfloat)m_vertMarkWidth); glBegin(GL_POINTS); for (unsigned i=0; i<vertCount; ++i) { ccGL::Vertex3v(getPoint(i)->u); } glEnd(); glPopAttrib(); } if (pushName) glPopName(); } }
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 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 cc2DLabel::drawMeOnly3D(CC_DRAW_CONTEXT& context) { assert(!m_points.empty()); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not particularily fast if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); } const float c_sizeFactor = 4.0f; bool loop = false; size_t count = m_points.size(); switch (count) { case 3: { glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); //we draw the triangle glColor4ub(255,255,0,128); glBegin(GL_TRIANGLES); ccGL::Vertex3v(m_points[0].cloud->getPoint(m_points[0].index)->u); ccGL::Vertex3v(m_points[1].cloud->getPoint(m_points[1].index)->u); ccGL::Vertex3v(m_points[2].cloud->getPoint(m_points[2].index)->u); glEnd(); glPopAttrib(); loop = true; } case 2: { //segment width glPushAttrib(GL_LINE_BIT); glLineWidth(c_sizeFactor * context.renderZoom); //we draw the segments if (isSelected()) ccGL::Color3v(ccColor::red.rgba); else ccGL::Color3v(ccColor::green.rgba); glBegin(GL_LINES); for (unsigned i=0; i<count; i++) { if (i+1<count || loop) { ccGL::Vertex3v(m_points[i].cloud->getPoint(m_points[i].index)->u); ccGL::Vertex3v(m_points[(i+1)%count].cloud->getPoint(m_points[(i+1)%count].index)->u); } } glEnd(); 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.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! markerContext._win = 0; if (isSelected() && !pushName) c_unitPointMarker->setTempColor(ccColor::red); else c_unitPointMarker->setTempColor(context.labelDefaultMarkerCol); for (unsigned i=0; i<count; i++) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); const CCVector3* P = m_points[i].cloud->getPoint(m_points[i].index); ccGL::Translate(P->x,P->y,P->z); glScalef(context.labelMarkerSize,context.labelMarkerSize,context.labelMarkerSize); c_unitPointMarker->draw(markerContext); glPopMatrix(); } } if (m_dispIn3D && !pushName) //no need to display label in point picking mode { QFont font(context._win->getTextDisplayFont()); //takes rendering zoom into account! //font.setPointSize(font.pointSize()+2); font.setBold(true); static const QChar ABC[3] = {'A','B','C'}; int VP[4]; context._win->getViewportArray(VP); const double* MM = context._win->getModelViewMatd(); //viewMat const double* MP = context._win->getProjectionMatd(); //projMat //draw their name glPushAttrib(GL_DEPTH_BUFFER_BIT); 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 GLdouble xp,yp,zp; gluProject(P->x,P->y,P->z,MM,MP,VP,&xp,&yp,&zp); context._win->displayText( title, static_cast<int>(xp) + context.labelMarkerTextShift_pix, static_cast<int>(yp) + context.labelMarkerTextShift_pix, ccGenericGLDisplay::ALIGN_DEFAULT, context.labelOpacity/100.0f, ccColor::white.rgba, &font ); } glPopAttrib(); } } } if (pushName) glPopName(); }
void ccGBLSensor::drawMeOnly(CC_DRAW_CONTEXT& context) { //we draw here a little 3d representation of the sensor if (MACRO_Draw3D(context)) { bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not particulary fast if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); } //DGM FIXME: this display routine is crap! //apply rigid transformation glMatrixMode(GL_MODELVIEW); glPushMatrix(); { ccIndexedTransformation sensorPos; if (!getAbsoluteTransformation(sensorPos,m_activeIndex)) { //no visible position for this index! glPopMatrix(); if (pushName) glPopName(); return; } glMultMatrixf(sensorPos.data()); } //test: center as sphere /*{ ccSphere sphere(m_scale/10,0,"Center",12); sphere.showColors(true); sphere.setVisible(true); sphere.setEnabled(true); CC_DRAW_CONTEXT sphereContext = context; sphereContext.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! sphereContext._win = 0; sphere.setTempColor(ccColor::magenta); sphere.draw(sphereContext); } //*/ const PointCoordinateType halfHeadSize = static_cast<PointCoordinateType>(0.3); //sensor axes { //increased width glPushAttrib(GL_LINE_BIT); GLfloat width; glGetFloatv(GL_LINE_WIDTH,&width); glLineWidth(width+1); PointCoordinateType axisLength = halfHeadSize * m_scale; ccGL::Color3v(ccColor::red.rgba); CCVector3 C(0,0,0); glBegin(GL_LINES); ccGL::Vertex3v(C.u); ccGL::Vertex3(C.x+axisLength,C.y,C.z); glEnd(); ccGL::Color3v(ccColor::green.rgba); glBegin(GL_LINES); ccGL::Vertex3v(C.u); ccGL::Vertex3(C.x,C.y+axisLength,C.z); glEnd(); ccGL::Color3v(ccColor::blue.rgba); glBegin(GL_LINES); ccGL::Vertex3v(C.u); ccGL::Vertex3(C.x,C.y,C.z+axisLength); glEnd(); glPopAttrib(); } //sensor head { CCVector3 minCorner(-halfHeadSize,-halfHeadSize,-halfHeadSize); CCVector3 maxCorner( halfHeadSize, halfHeadSize, halfHeadSize); minCorner *= m_scale; maxCorner *= m_scale; ccBBox bbHead(minCorner,maxCorner); bbHead.draw(m_color); } //sensor legs { CCVector3 headConnect = /*headCenter*/ - CCVector3(0,0,static_cast<PointCoordinateType>(halfHeadSize)*m_scale); ccGL::Color3v(m_color.rgb); glBegin(GL_LINES); ccGL::Vertex3v(headConnect.u); ccGL::Vertex3(-m_scale,-m_scale,-m_scale); ccGL::Vertex3v(headConnect.u); ccGL::Vertex3(-m_scale,m_scale,-m_scale); ccGL::Vertex3v(headConnect.u); ccGL::Vertex3(m_scale,0,-m_scale); glEnd(); } if (pushName) glPopName(); glPopMatrix(); } }
void cc2DLabel::drawMeOnly2D(CC_DRAW_CONTEXT& context) { if (!m_dispIn2D) return; assert(!m_points.empty()); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueID()); //we should already be in orthoprojective & centered omde //glOrtho(-halfW,halfW,-halfH,halfH,-maxS,maxS); int strHeight = 0; int titleHeight = 0; QString title(getName()); QStringList body; 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 /= (PointCoordinateType)m_points.size(); //project it in 2D screen coordinates int VP[4]; context._win->getViewportArray(VP); const double* MM = context._win->getModelViewMatd(); //viewMat const double* MP = context._win->getProjectionMatd(); //projMat GLdouble zp; gluProject(arrowDest.x,arrowDest.y,arrowDest.z,MM,MP,VP,&arrowDestX,&arrowDestY,&zp); /*** label border ***/ bodyFont = context._win->getTextDisplayFont(); //takes rendering zoom into account! titleFont = QFont(context._win->getTextDisplayFont()); //takes rendering zoom into account! titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); QFontMetrics bodyFontMetrics(bodyFont); strHeight = bodyFontMetrics.height(); titleHeight = titleFontMetrics.height(); if (m_showFullBody) body = getLabelContent(context.dispNumberPrecision); //base box dimension int dx = 150; dx = std::max(dx,titleFontMetrics.width(title)); int dy = c_margin; //top vertical margin dy += titleHeight; //title if (!body.empty()) { dy += c_margin; //vertical margin above separator for (int j=0;j<body.size();++j) { dx = std::max(dx,bodyFontMetrics.width(body[j])); dy += (c_margin+strHeight); //margin + body line height } } else { dy += c_margin; // vertical margin (purely for aesthetics) } dy += c_margin; // bottom vertical margin dx += c_margin*2; // horizontal margins //main rectangle m_labelROI[0]=0; m_labelROI[1]=0; m_labelROI[2]=dx; m_labelROI[3]=dy; //close button /*m_closeButtonROI[2]=dx-c_margin; m_closeButtonROI[0]=m_closeButtonROI[2]-c_buttonSize; m_closeButtonROI[3]=c_margin; m_closeButtonROI[1]=m_closeButtonROI[3]+c_buttonSize; //*/ //automatically elide the title //title = titleFontMetrics.elidedText(title,Qt::ElideRight,m_closeButtonROI[0]-2*c_margin); } int halfW = (context.glW>>1); int halfH = (context.glH>>1); //draw label rectangle int xStart = m_lastScreenPos[0] = (int)((float)context.glW * m_screenPos[0]); int yStart = m_lastScreenPos[1] = (int)((float)context.glH * (1.0f-m_screenPos[1])); //colors bool highlighted = (!pushName && isSelected()); //default background color colorType defaultBkgColor[4]; memcpy(defaultBkgColor,context.labelDefaultCol,sizeof(colorType)*3); defaultBkgColor[3] = (colorType)((float)context.labelsTransparency*(float)MAX_COLOR_COMP/100.0f); //default border color (mustn't be totally transparent!) colorType defaultBorderColor[4]; if (highlighted) memcpy(defaultBorderColor,ccColor::red,sizeof(colorType)*3); else memcpy(defaultBorderColor,context.labelDefaultCol,sizeof(colorType)*3); defaultBorderColor[3] = (colorType)((float)(50+context.labelsTransparency/2)*(float)MAX_COLOR_COMP/100.0f); glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glMatrixMode(GL_MODELVIEW); glPushMatrix(); 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 = (int)arrowDestX-xStart; int iArrowDestY = (int)arrowDestY-yStart; { if (iArrowDestX < m_labelROI[0]) //left arrowBaseConfig += 0; else if (iArrowDestX > m_labelROI[2]) //Right arrowBaseConfig += 2; else //Middle arrowBaseConfig += 1; if (iArrowDestY > -m_labelROI[1]) //Top arrowBaseConfig += 0; else if (iArrowDestY < -m_labelROI[3]) //Bottom arrowBaseConfig += 6; else //Middle arrowBaseConfig += 3; } //we make the arrow base start from the nearest corner if (arrowBaseConfig != 4) //4 = label above point! { glColor4ubv(defaultBorderColor); glBegin(GL_TRIANGLE_FAN); glVertex2d(arrowDestX-xStart,arrowDestY-yStart); switch(arrowBaseConfig) { case 0: //top-left corner glVertex2i(m_labelROI[0], -m_labelROI[1]-2*c_arrowBaseSize); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0]+2*c_arrowBaseSize, -m_labelROI[1]); break; case 1: //top-middle edge glVertex2i(std::max(m_labelROI[0],iArrowDestX-c_arrowBaseSize), -m_labelROI[1]); glVertex2i(std::min(m_labelROI[2],iArrowDestX+c_arrowBaseSize), -m_labelROI[1]); break; case 2: //top-right corner glVertex2i(m_labelROI[2], -m_labelROI[1]-2*c_arrowBaseSize); glVertex2i(m_labelROI[2], -m_labelROI[1]); glVertex2i(m_labelROI[2]-2*c_arrowBaseSize, -m_labelROI[1]); break; case 3: //middle-left edge glVertex2i(m_labelROI[0], std::min(-m_labelROI[1],iArrowDestY+c_arrowBaseSize)); glVertex2i(m_labelROI[0], std::max(-m_labelROI[3],iArrowDestY-c_arrowBaseSize)); break; case 4: //middle of rectangle! break; case 5: //middle-right edge glVertex2i(m_labelROI[2], std::min(-m_labelROI[1],iArrowDestY+c_arrowBaseSize)); glVertex2i(m_labelROI[2], std::max(-m_labelROI[3],iArrowDestY-c_arrowBaseSize)); break; case 6: //bottom-left corner glVertex2i(m_labelROI[0], -m_labelROI[3]+2*c_arrowBaseSize); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[0]+2*c_arrowBaseSize, -m_labelROI[3]); break; case 7: //bottom-middle edge glVertex2i(std::max(m_labelROI[0],iArrowDestX-c_arrowBaseSize), -m_labelROI[3]); glVertex2i(std::min(m_labelROI[2],iArrowDestX+c_arrowBaseSize), -m_labelROI[3]); break; case 8: //bottom-right corner glVertex2i(m_labelROI[2], -m_labelROI[3]+2*c_arrowBaseSize); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2]-2*c_arrowBaseSize, -m_labelROI[3]); break; } glEnd(); } } //main rectangle glColor4ubv(defaultBkgColor); glBegin(GL_QUADS); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[1]); glEnd(); //if (highlighted) { glPushAttrib(GL_LINE_BIT); glLineWidth(3.0f); glColor4ubv(defaultBorderColor); glBegin(GL_LINE_LOOP); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[1]); glEnd(); glPopAttrib(); } //draw close button /*glColor3ubv(ccColor::black); glBegin(GL_LINE_LOOP); glVertex2i(m_closeButtonROI[0],-m_closeButtonROI[1]); glVertex2i(m_closeButtonROI[0],-m_closeButtonROI[3]); glVertex2i(m_closeButtonROI[2],-m_closeButtonROI[3]); glVertex2i(m_closeButtonROI[2],-m_closeButtonROI[1]); glEnd(); glBegin(GL_LINES); glVertex2i(m_closeButtonROI[0]+2,-m_closeButtonROI[1]+2); glVertex2i(m_closeButtonROI[2]-2,-m_closeButtonROI[3]-2); glVertex2i(m_closeButtonROI[2]-2,-m_closeButtonROI[1]+2); glVertex2i(m_closeButtonROI[0]+2,-m_closeButtonROI[3]-2); glEnd(); //*/ //display text if (!pushName) { int xStartRel = c_margin; int yStartRel = -c_margin; yStartRel -= titleHeight; const colorType* defaultTextColor = (context.labelsTransparency<40 ? context.textDefaultCol : ccColor::darkBlue); context._win->displayText(title,xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor,&titleFont); yStartRel -= c_margin; if (!body.empty()) { //line separation glColor4ubv(defaultBorderColor); glBegin(GL_LINES); glVertex2i(xStartRel,yStartRel); glVertex2i(xStartRel+m_labelROI[2]-m_labelROI[0]-2*c_margin,yStartRel); glEnd(); //display body yStartRel -= c_margin; for (int i=0;i<body.size();++i) { yStartRel -= strHeight; context._win->displayText(body[i],xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor,&bodyFont); } } } glPopAttrib(); glPopMatrix(); if (pushName) glPopName(); }
void cc2DLabel::drawMeOnly3D(CC_DRAW_CONTEXT& context) { assert(!m_points.empty()); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) { //not particularily fast if (MACRO_DrawFastNamesOnly(context)) return; glPushName(getUniqueIDForDisplay()); } const float c_sizeFactor = 4.0f; bool loop=false; size_t count = m_points.size(); switch (count) { case 3: { glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); //we draw the triangle glColor4ub(255,255,0,128); glBegin(GL_TRIANGLES); for (unsigned i=0; i<count; ++i) ccGL::Vertex3v(m_points[i].cloud->getPoint(m_points[i].index)->u); glEnd(); glPopAttrib(); loop=true; } case 2: { //segment width glPushAttrib(GL_LINE_BIT); glLineWidth(c_sizeFactor); //we draw the segments if (isSelected()) glColor3ubv(ccColor::red); else glColor3ubv(ccColor::green); glBegin(GL_LINES); for (unsigned i=0; i<count; i++) { if (i+1<count || loop) { ccGL::Vertex3v(m_points[i].cloud->getPoint(m_points[i].index)->u); ccGL::Vertex3v(m_points[(i+1)%count].cloud->getPoint(m_points[(i+1)%count].index)->u); } } glEnd(); 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.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own! markerContext._win = 0; if (isSelected() && !pushName) c_unitPointMarker->setTempColor(ccColor::red); else c_unitPointMarker->setTempColor(ccColor::magenta); for (unsigned i=0; i<count; i++) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); const CCVector3* P = m_points[i].cloud->getPoint(m_points[i].index); ccGL::Translate(P->x,P->y,P->z); glScalef(context.pickedPointsRadius,context.pickedPointsRadius,context.pickedPointsRadius); c_unitPointMarker->draw(markerContext); glPopMatrix(); } } if (m_dispIn3D && !pushName) //no need to display label in point picking mode { QFont font(context._win->getTextDisplayFont()); //takes rendering zoom into account! //font.setPointSize(font.pointSize()+2); font.setBold(true); //draw their name glPushAttrib(GL_DEPTH_BUFFER_BIT); 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 = (count == 1 ? getName() : QString("P#%0").arg(m_points[j].index)); context._win->display3DLabel( title, *P+CCVector3(context.pickedPointsTextShift), ccColor::magenta, font); } glPopAttrib(); } } } if (pushName) glPopName(); }
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 ccPolyline::drawMeOnly(CC_DRAW_CONTEXT& context) { //no picking enabled on polylines if (MACRO_DrawPointNames(context)) return; 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) { //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueIDForDisplay()); if (colorsShown()) glColor3ubv(m_rgbColor); //display polyline { if (m_width != 0) { glPushAttrib(GL_LINE_BIT); glLineWidth(static_cast<GLfloat>(m_width)); } glBegin(m_isClosed ? GL_LINE_LOOP : GL_LINE_STRIP); for (unsigned i=0; i<vertCount; ++i) { ccGL::Vertex3v(getPoint(i)->u); } glEnd(); if (m_width != 0) { glPopAttrib(); } } //display vertices if (m_showVertices) { glPushAttrib(GL_POINT_BIT); glPointSize((GLfloat)m_vertMarkWidth); glBegin(GL_POINTS); for (unsigned i=0; i<vertCount; ++i) { ccGL::Vertex3v(getPoint(i)->u); } glEnd(); glPopAttrib(); } if (pushName) glPopName(); } }