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 ccHObject::draw(CC_DRAW_CONTEXT& context) { if (!isEnabled()) return; bool draw3D = MACRO_Draw3D(context); bool drawInThisContext = (!m_visible && !m_selected ? false : m_currentDisplay == context._win); //no need to display anything but clouds and meshes in "point picking mode" bool DrawMesh = false; if (MACRO_DrawTriangleNames(context) && isKindOf(CC_MESH)) { ccGenericMesh *mesh = static_cast<ccGenericMesh*>(this); ccGenericPointCloud *cloud = mesh->getAssociatedCloud(); DrawMesh = (cloud == NULL || !cloud->isEnabled()); } drawInThisContext &= ( (!MACRO_DrawPointNames(context) || isKindOf(CC_POINT_CLOUD)) || (!MACRO_DrawTriangleNames(context) || DrawMesh) ); //apply 3D 'temporary' transformation (for display only) if (draw3D && m_glTransEnabled) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(m_glTrans.data()); } //draw entity if (m_visible && drawInThisContext) { if ((!m_selected || !MACRO_SkipSelected(context)) && (m_selected || !MACRO_SkipUnselected(context))) { glColor3ubv(context.pointsDefaultCol); drawMeOnly(context); //draw name in 3D (we display it in the 2D foreground layer in fact!) if (m_showNameIn3D && MACRO_Draw2D(context) && MACRO_Foreground(context) && !MACRO_DrawNames(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 if (m_selected && draw3D && drawInThisContext) { switch (m_selectionBehavior) { case SELECTION_AA_BBOX: drawBB(context.bbDefaultCol); break; case SELECTION_FIT_BBOX: { ccGLMatrix trans; ccBBox box = getFitBB(trans); if (box.isValid()) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(trans.data()); box.draw(context.bbDefaultCol); glPopMatrix(); } } break; case SELECTION_IGNORED: break; default: assert(false); } } if (draw3D && m_glTransEnabled) glPopMatrix(); }
void ccHObject::draw(CC_DRAW_CONTEXT& context) { if (!isEnabled()) return; //are we currently drawing objects in 2D or 3D? bool draw3D = MACRO_Draw3D(context); //the entity must be either visible and selected, and of course it should be displayed in this context bool drawInThisContext = ((m_visible || m_selected) && m_currentDisplay == context._win); //no need to display anything but clouds and meshes in "element picking mode" drawInThisContext &= ( ( !MACRO_DrawPointNames(context) || isKindOf(CC_TYPES::POINT_CLOUD) ) || ( !MACRO_DrawTriangleNames(context) || isKindOf(CC_TYPES::MESH) )); //apply 3D 'temporary' transformation (for display only) if (draw3D && m_glTransEnabled) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(m_glTrans.data()); } //draw entity if (m_visible && drawInThisContext) { if (( !m_selected || !MACRO_SkipSelected(context) ) && ( m_selected || !MACRO_SkipUnselected(context) )) { //apply default color (in case of) glColor3ubv(context.pointsDefaultCol); drawMeOnly(context); //draw name in 3D (we display it in the 2D foreground layer in fact!) if (m_showNameIn3D && MACRO_Draw2D(context) && MACRO_Foreground(context) && !MACRO_DrawNames(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_DrawNames(context)) { switch (m_selectionBehavior) { case SELECTION_AA_BBOX: drawBB(context.bbDefaultCol); break; case SELECTION_FIT_BBOX: { ccGLMatrix trans; ccBBox box = getFitBB(trans); if (box.isValid()) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(trans.data()); box.draw(context.bbDefaultCol); glPopMatrix(); } } break; case SELECTION_IGNORED: break; default: assert(false); } } if (draw3D && m_glTransEnabled) glPopMatrix(); }
//================================================draw====================================================// void ccHObject::draw(CC_DRAW_CONTEXT& context) { if (!isEnabled())return; //是否开启 //are we currently drawing objects in 2D or 3D? bool draw3D = MACRO_Draw3D(context); //判断是在三维上绘制还是在二维上绘制? //the entity must be either visible and selected, and of course it should be displayed in this context //是否可视,是否被选择,是否在当前窗口下显示 bool drawInThisContext = ((m_visible || m_selected) && m_currentDisplay == context._win); //no need to display anything but clouds and meshes in "element picking mode" drawInThisContext &= ( ( !MACRO_DrawPointNames(context) || isKindOf(CC_TYPES::POINT_CLOUD) ) || ( !MACRO_DrawTriangleNames(context) || isKindOf(CC_TYPES::MESH) )); if (draw3D){ //apply 3D 'temporary' transformation (for display only) if (m_glTransEnabled){ //可以进行变换 glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(m_glTrans.data()); } if ( context.decimateCloudOnMove //LOD for clouds is enabled? && context.currentLODLevel >= context.minLODLevel //and we are currently rendering higher levels? ){ //only for real clouds drawInThisContext &= isA(CC_TYPES::POINT_CLOUD); //LOD只对点云有效?????????? } } //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(context.pointsDefaultCol.rgb); //不同的物体绘制方式不同 drawMeOnly(context); //draw name in 3D (we display it in the 2D foreground layer in fact!) if (m_showNameIn3D && MACRO_Draw2D(context) && MACRO_Foreground(context) && !MACRO_DrawNames(context)) drawNameIn3D(context); } } //draw entity's children //绘制物体的子物体 for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) (*it)->draw(context); //绘制BB //if the entity is currently selected, we draw its bounding-box if (m_selected && draw3D && drawInThisContext && !MACRO_DrawNames(context) && context.currentLODLevel == 0){ drawBB(context.bbDefaultCol); } if (draw3D && m_glTransEnabled) glPopMatrix(); }