void ccHObject::applyGLTransformation_recursive(ccGLMatrix* trans/*=NULL*/) { ccGLMatrix* _trans = NULL; if (m_glTransEnabled) { if (!trans) { //if no transformation is provided (by father) //we initiate it with the current one trans = _trans = new ccGLMatrix(m_glTrans); } else { *trans *= m_glTrans; } } if (trans) { applyGLTransformation(*trans); notifyGeometryUpdate(); } for (Container::iterator it = m_children.begin(); it!=m_children.end(); ++it) (*it)->applyGLTransformation_recursive(trans); if (_trans) delete _trans; if (m_glTransEnabled) resetGLTransformation(); }
void ccHObject::applyGLTransformation_recursive(const ccGLMatrix* transInput/*=NULL*/) { ccGLMatrix transTemp; const ccGLMatrix* transToApply = transInput; if (m_glTransEnabled) { if (!transInput) { //if no transformation is provided (by father) //we initiate it with the current one transToApply = &m_glTrans; } else { transTemp = *transInput * m_glTrans; transToApply = &transTemp; } } if (transToApply) { applyGLTransformation(*transToApply); notifyGeometryUpdate(); } for (Container::iterator it = m_children.begin(); it!=m_children.end(); ++it) (*it)->applyGLTransformation_recursive(transToApply); if (m_glTransEnabled) resetGLTransformation(); }
//==================================================applyGLTransformation_recursive======================================// void ccHObject::applyGLTransformation_recursive(ccGLMatrix* trans/*=NULL*/) { ccGLMatrix* _trans = NULL; if (m_glTransEnabled){ if (!trans) { //if no transformation is provided (by father) //we initiate it with the current one trans = _trans = new ccGLMatrix(m_glTrans); } else{ //将trans 作用到m_glTrans *trans *= m_glTrans; } } //将trans作用到该物体,并提醒相互依赖的物体进行升级 if (trans){ applyGLTransformation(*trans); notifyGeometryUpdate(); } //对于每一个子物体,进行递归变换 for (Container::iterator it = m_children.begin(); it!=m_children.end(); ++it) (*it)->applyGLTransformation_recursive(trans); if (_trans) delete _trans; //变换完成后,进行禁止变换,对于递归函数非常重要 if (m_glTransEnabled) resetGLTransformation(); }
void ccSubMesh::refreshBB() { m_bBox.clear(); for (unsigned i=0; i<size(); ++i) { CCLib::GenericTriangle* tri = _getTriangle(i); m_bBox.add(*tri->_getA()); m_bBox.add(*tri->_getB()); m_bBox.add(*tri->_getC()); } notifyGeometryUpdate(); }
bool ccTorus::buildUp() { if (m_drawPrecision<4) return false; //invalid parameters? if ((m_rectSection && m_rectSectionHeight < ZERO_TOLERANCE) || m_insideRadius >= m_outsideRadius || m_angle_rad < ZERO_TOLERANCE) return false; //topology bool closed = (m_angle_rad >= 2.0*M_PI); const unsigned steps = m_drawPrecision; unsigned sweepSteps = 4*(closed ? steps : (unsigned)ceil(m_angle_rad*(double)steps/(2.0*M_PI))); unsigned sectSteps = (m_rectSection ? 4 : steps); //vertices unsigned vertCount = (sweepSteps+(closed ? 0 : 1))*sectSteps; //DGM: +1 row for non closed loops //faces unsigned facesCount = sweepSteps*sectSteps*2; //faces normals unsigned faceNormCount = (sweepSteps+(closed ? 0 : 1))*sectSteps; //DGM: +1 row for non closed loops if (!closed) facesCount += (m_rectSection ? 2 : sectSteps)*2; if (!init(vertCount+(closed || m_rectSection ? 0 : 2),false,facesCount,faceNormCount+(closed ? 0 : 2))) { ccLog::Error("[ccTorus::buildUp] Not enough memory"); return false; } //2D section CCVector3* sectPoints = new CCVector3[sectSteps]; if (!sectPoints) { init(0,false,0,0); ccLog::Error("[ccTorus::buildUp] Not enough memory"); return false; } PointCoordinateType sectionRadius = (m_outsideRadius-m_insideRadius)/2; if (m_rectSection) { //rectangular section sectPoints[0].x = (m_outsideRadius-m_insideRadius)/2; sectPoints[0].z = m_rectSectionHeight/2; sectPoints[1].x = -sectPoints[0].x; sectPoints[1].z = sectPoints[0].z; sectPoints[2].x = sectPoints[1].x; sectPoints[2].z = -sectPoints[1].z; sectPoints[3].x = -sectPoints[2].x; sectPoints[3].z = sectPoints[2].z; } else { //circular section for (unsigned i=0;i<sectSteps;++i) { float sect_angle_rad = (float)i/(float)sectSteps*(float)(2.0*M_PI); sectPoints[i].x = cos(sect_angle_rad) * sectionRadius; sectPoints[i].z = sin(sect_angle_rad) * sectionRadius; } } ccPointCloud* verts = vertices(); assert(verts); assert(m_triNormals); //main sweep PointCoordinateType sweepRadius = (m_insideRadius+m_outsideRadius)/(PointCoordinateType)2.0; double sweepStep_rad = m_angle_rad/(double)sweepSteps; for (unsigned t=0; t<(closed ? sweepSteps : sweepSteps+1); ++t) { //unit director vector CCVector3 sweepU(static_cast<PointCoordinateType>(cos(t*sweepStep_rad)), static_cast<PointCoordinateType>(sin(t*sweepStep_rad)), 0); //section points for (unsigned i=0;i<sectSteps;++i) { CCVector3 P(sweepU.x * (sweepRadius + sectPoints[i].x), sweepU.y * (sweepRadius + sectPoints[i].x), sectPoints[i].z); verts->addPoint(P); } //normals if (m_rectSection) { m_triNormals->addElement(ccNormalVectors::GetNormIndex(CCVector3(0.0,0.0,1.0).u)); m_triNormals->addElement(ccNormalVectors::GetNormIndex((-sweepU).u)); m_triNormals->addElement(ccNormalVectors::GetNormIndex(CCVector3(0.0,0.0,-1.0).u)); m_triNormals->addElement(ccNormalVectors::GetNormIndex((-sweepU).u)); } else //circular section { for (unsigned i=0;i<sectSteps;++i) { float sectAngle_rad = (float)i/(float)sectSteps*(float)(2.0*M_PI); CCVector3 sectU(cos(sectAngle_rad),0.0,sin(sectAngle_rad)); CCVector3 N(sweepU.x * sectU.x, sweepU.y * sectU.x, sectU.z); m_triNormals->addElement(ccNormalVectors::GetNormIndex(N.u)); } } } if (!closed && !m_rectSection) { CCVector3 P(sweepRadius,0,0); verts->addPoint(P); CCVector3 P2( static_cast<PointCoordinateType>(cos(m_angle_rad))*sweepRadius, static_cast<PointCoordinateType>(sin(m_angle_rad))*sweepRadius, 0); verts->addPoint(P2); } if (!closed) { //first section (left side) m_triNormals->addElement(ccNormalVectors::GetNormIndex(CCVector3(0,-1,0).u)); //last section (right side) m_triNormals->addElement(ccNormalVectors::GetNormIndex(CCVector3( static_cast<PointCoordinateType>(-sin(m_angle_rad)), static_cast<PointCoordinateType>(cos(m_angle_rad)), 0).u)); } delete[] sectPoints; sectPoints=0; //mesh faces { assert(m_triVertIndexes); for (unsigned t=0;t<sweepSteps;++t) { unsigned sweepStart = t*sectSteps; for (unsigned i=0;i<sectSteps;++i) { unsigned iNext = (i+1)%sectSteps; addTriangle(sweepStart+i,(sweepStart+i+sectSteps)%vertCount,(sweepStart+iNext+sectSteps)%vertCount); if (m_rectSection) addTriangleNormalIndexes(sweepStart+i,(sweepStart+i+sectSteps)%faceNormCount,(sweepStart+i+sectSteps)%faceNormCount); else addTriangleNormalIndexes(sweepStart+i,(sweepStart+i+sectSteps)%faceNormCount,(sweepStart+iNext+sectSteps)%faceNormCount); addTriangle(sweepStart+i,(sweepStart+iNext+sectSteps)%vertCount,sweepStart+iNext); if (m_rectSection) addTriangleNormalIndexes(sweepStart+i,(sweepStart+i+sectSteps)%faceNormCount,sweepStart+i); else addTriangleNormalIndexes(sweepStart+i,(sweepStart+iNext+sectSteps)%faceNormCount,sweepStart+iNext); } } if (!closed) { unsigned lastSectionShift = sweepSteps*sectSteps; if (m_rectSection) { //rectangular left section addTriangle(0,1,2); addTriangleNormalIndexes(faceNormCount,faceNormCount,faceNormCount); addTriangle(0,2,3); addTriangleNormalIndexes(faceNormCount,faceNormCount,faceNormCount); //rectangular right section addTriangle(lastSectionShift,lastSectionShift+2,lastSectionShift+1); addTriangleNormalIndexes(faceNormCount+1,faceNormCount+1,faceNormCount+1); addTriangle(lastSectionShift,lastSectionShift+3,lastSectionShift+2); addTriangleNormalIndexes(faceNormCount+1,faceNormCount+1,faceNormCount+1); } else { unsigned lastSectionCenterShift = vertCount; //circular 'left' section for (unsigned i=0;i<sectSteps;++i) { unsigned iNext = (i+1)%sectSteps; addTriangle(lastSectionCenterShift,i,iNext); addTriangleNormalIndexes(faceNormCount,faceNormCount,faceNormCount); } //circular 'right' section for (unsigned i=0;i<sectSteps;++i) { unsigned iNext = (i+1)%sectSteps; addTriangle(lastSectionCenterShift+1,lastSectionShift+iNext,lastSectionShift+i); addTriangleNormalIndexes(faceNormCount+1,faceNormCount+1,faceNormCount+1); } } } } notifyGeometryUpdate(); showTriNorms(true); return true; }
bool ccDish::buildUp() { if (m_drawPrecision < MIN_DRAWING_PRECISION) return false; if (m_height <= 0 || m_baseRadius <= 0 || m_secondRadius < 0) //invalid parameters return false; //section angular span double startAngle_rad = 0.0; const double endAngle_rad = M_PI/2.0; PointCoordinateType realRadius = m_baseRadius; if (m_secondRadius == 0 && m_height<m_baseRadius) //partial spherical mode { realRadius = (m_height*m_height+m_baseRadius*m_baseRadius)/(2*m_height); startAngle_rad = acos(m_baseRadius/realRadius); assert(startAngle_rad<endAngle_rad); } const unsigned steps = m_drawPrecision; double angleStep_rad = 2.0*M_PI/steps; unsigned sectionSteps = static_cast<unsigned>(ceil((endAngle_rad-startAngle_rad)*m_drawPrecision/(2.0*M_PI))); double sectionAngleStep_rad = (endAngle_rad-startAngle_rad)/sectionSteps; //vertices unsigned vertCount = steps*sectionSteps+1; //+1 for noth pole //faces unsigned faceCount = steps*((sectionSteps-1)*2+1); if (!init(vertCount,true,faceCount,0)) { ccLog::Error("[ccDish::buildUp] Not enough memory"); return false; } //vertices ccPointCloud* verts = vertices(); assert(verts); //first point: north pole verts->addPoint(CCVector3(0,0,m_height)); verts->addNorm(CCVector3(0,0,1)); //then, angular sweep { for (unsigned j=1; j<=sectionSteps; ++j) { PointCoordinateType theta = static_cast<PointCoordinateType>(endAngle_rad - j * sectionAngleStep_rad); //we start from north pole! PointCoordinateType cos_theta = cos(theta); PointCoordinateType sin_theta = sin(theta); CCVector3 N0(cos_theta, 0, sin_theta); for (unsigned i=0; i<steps; ++i) //then we make a full revolution { PointCoordinateType phi = static_cast<PointCoordinateType>(i * angleStep_rad); PointCoordinateType cos_phi = cos(phi); PointCoordinateType sin_phi = sin(phi); CCVector3 N(N0.x * cos_phi, N0.x * sin_phi, N0.z); N.normalize(); CCVector3 P = N * realRadius; if (m_secondRadius > 0) //half-ellipsoid mode { P.y *= (m_secondRadius / m_baseRadius); P.z *= (m_height / m_baseRadius); } else //spherical section mode { P.z += m_height-realRadius; } verts->addPoint(P); verts->addNorm(N); } } } //faces { //north pole { for (unsigned i=0; i<steps; ++i) { unsigned A = 1+i; unsigned B = (i+1<steps ? A+1 : 1); addTriangle(A,B,0); } } //slices for (unsigned j=1; j<sectionSteps; ++j) { unsigned shift = 1+(j-1)*steps; for (unsigned i=0; i<steps; ++i) { unsigned A = shift+i; unsigned B = (i+1<steps ? A+1 : shift); assert(B < vertCount); addTriangle(A,A+steps,B); addTriangle(B+steps,B,A+steps); } } } notifyGeometryUpdate(); showNormals(true); return true; }
bool ccCone::buildUp() { if (m_drawPrecision < MIN_DRAWING_PRECISION) return false; //invalid dimensions? if (m_height < ZERO_TOLERANCE || m_bottomRadius + m_topRadius < ZERO_TOLERANCE) return false; //topology bool singlePointBottom = (m_bottomRadius < ZERO_TOLERANCE); bool singlePointTop = (m_topRadius < ZERO_TOLERANCE); assert(!singlePointBottom || !singlePointTop); unsigned steps = m_drawPrecision; //vertices unsigned vertCount = 2; if (!singlePointBottom) vertCount += steps; if (!singlePointTop) vertCount += steps; //normals unsigned faceNormCounts = steps+2; //vertices unsigned facesCount = steps; if (!singlePointBottom) facesCount += steps; if (!singlePointTop) facesCount += steps; if (!singlePointBottom && !singlePointTop) facesCount += steps; //allocate (& clear) structures if (!init(vertCount,false,facesCount,faceNormCounts)) { ccLog::Error("[ccCone::buildUp] Not enough memory"); return false; } ccPointCloud* verts = vertices(); assert(verts); assert(m_triNormals); //2 first points: centers of the top & bottom surfaces CCVector3 bottomCenter = CCVector3(m_xOff,m_yOff,-m_height)/2; CCVector3 topCenter = CCVector3(-m_xOff,-m_yOff,m_height)/2; { //bottom center verts->addPoint(bottomCenter); CompressedNormType nIndex = ccNormalVectors::GetNormIndex(CCVector3(0,0,-1).u); m_triNormals->addElement(nIndex); //top center verts->addPoint(topCenter); nIndex = ccNormalVectors::GetNormIndex(CCVector3(0,0,1).u); m_triNormals->addElement(nIndex); } //then, angular sweep for top and/or bottom surfaces { PointCoordinateType angle_rad_step = static_cast<PointCoordinateType>(2.0*M_PI)/static_cast<PointCoordinateType>(steps); //bottom surface if (!singlePointBottom) { for (unsigned i=0; i<steps; ++i) { CCVector3 P(bottomCenter.x + cos(angle_rad_step*i)*m_bottomRadius, bottomCenter.y + sin(angle_rad_step*i)*m_bottomRadius, bottomCenter.z); verts->addPoint(P); } } //top surface if (!singlePointTop) { for (unsigned i=0; i<steps; ++i) { CCVector3 P(topCenter.x + cos(angle_rad_step*i)*m_topRadius, topCenter.y + sin(angle_rad_step*i)*m_topRadius, topCenter.z); verts->addPoint(P); } } //side normals { for (unsigned i=0; i<steps; ++i) { //slope CCVector3 u(-sin(angle_rad_step*i),cos(angle_rad_step*i),0); CCVector3 v(bottomCenter.x-topCenter.x + u.y*(m_bottomRadius-m_topRadius), bottomCenter.y-topCenter.y - u.x*(m_bottomRadius-m_topRadius), bottomCenter.z-topCenter.z); CCVector3 N = v.cross(u); N.normalize(); CompressedNormType nIndex = ccNormalVectors::GetNormIndex(N.u); m_triNormals->addElement(nIndex); } } } //mesh faces { assert(m_triVertIndexes); unsigned bottomIndex = 2; unsigned topIndex = 2+(singlePointBottom ? 0 : steps); //bottom surface if (!singlePointBottom) { for (unsigned i=0;i<steps;++i) { addTriangle(0,bottomIndex+(i+1)%steps,bottomIndex+i); addTriangleNormalIndexes(0,0,0); } } //top surface if (!singlePointTop) { for (unsigned i=0;i<steps;++i) { addTriangle(1,topIndex+i,topIndex+(i+1)%steps); addTriangleNormalIndexes(1,1,1); } } if (!singlePointBottom && !singlePointTop) { for (unsigned i=0;i<steps;++i) { unsigned iNext = (i+1)%steps; addTriangle(bottomIndex+i,bottomIndex+iNext,topIndex+i); addTriangleNormalIndexes(2+i,2+iNext,2+i); addTriangle(topIndex+i,bottomIndex+iNext,topIndex+iNext); addTriangleNormalIndexes(2+i,2+iNext,2+iNext); } } else if (!singlePointTop) { for (unsigned i=0;i<steps;++i) { unsigned iNext = (i+1)%steps; addTriangle(topIndex+i,0,topIndex+iNext); addTriangleNormalIndexes(2+i,2+iNext,2+iNext); //TODO: middle normal should be halfbetween?! } } else //if (!singlePointBottom) { for (unsigned i=0;i<steps;++i) { unsigned iNext = (i+1)%steps; addTriangle(bottomIndex+i,bottomIndex+iNext,1); addTriangleNormalIndexes(2+i,2+iNext,2+i); //TODO: last normal should be halfbetween?! } } } notifyGeometryUpdate(); showTriNorms(true); return true; }
ccSubMesh* ccSubMesh::createNewSubMeshFromSelection(bool removeSelectedFaces, IndexMap* indexMap/*=0*/) { ccGenericPointCloud* vertices = getAssociatedCloud(); assert(vertices && m_associatedMesh); if (!vertices || !m_associatedMesh) { return NULL; } ccGenericPointCloud::VisibilityTableType* verticesVisibility = vertices->getTheVisibilityArray(); if (!verticesVisibility || !verticesVisibility->isAllocated()) { ccLog::Error(QString("[Sub-mesh %1] Internal error: vertex visibility table not instantiated!").arg(getName())); return NULL; } //we count the number of remaining faces unsigned triNum = m_triIndexes->currentSize(); unsigned visibleFaces = 0; { for (unsigned i=0; i<triNum; ++i) { const unsigned& globalIndex = m_triIndexes->getValue(i); const CCLib::VerticesIndexes* tsi = m_associatedMesh->getTriangleVertIndexes(globalIndex); //triangle is visible? if ( verticesVisibility->getValue(tsi->i1) == POINT_VISIBLE && verticesVisibility->getValue(tsi->i2) == POINT_VISIBLE && verticesVisibility->getValue(tsi->i3) == POINT_VISIBLE) { ++visibleFaces; } } } //nothing to do if (visibleFaces == 0) { if (indexMap) //we still have to translate global indexes! { for (unsigned i=0; i<triNum; ++i) { unsigned globalIndex = m_triIndexes->getValue(i); globalIndex = indexMap->getValue(globalIndex); m_triIndexes->setValue(i,globalIndex); } } return 0; } ccSubMesh* newSubMesh = new ccSubMesh(m_associatedMesh); if (!newSubMesh->reserve(size())) { ccLog::Error("[ccSubMesh::createNewSubMeshFromSelection] Not enough memory!"); return NULL; } //create sub-mesh { unsigned lastTri = 0; for (unsigned i=0; i<triNum; ++i) { unsigned globalIndex = m_triIndexes->getValue(i); const CCLib::VerticesIndexes* tsi = m_associatedMesh->getTriangleVertIndexes(globalIndex); if (indexMap) //translate global index? globalIndex = indexMap->getValue(globalIndex); //triangle is visible? if ( verticesVisibility->getValue(tsi->i1) == POINT_VISIBLE && verticesVisibility->getValue(tsi->i2) == POINT_VISIBLE && verticesVisibility->getValue(tsi->i3) == POINT_VISIBLE) { newSubMesh->addTriangleIndex(globalIndex); } else if (removeSelectedFaces) //triangle is not visible? It stays in the original mesh! { //we replace the current triangle by the 'last' valid one assert(lastTri <= i); m_triIndexes->setValue(lastTri++,globalIndex); } } //resize original mesh if (removeSelectedFaces && lastTri < triNum) { if (lastTri == 0) m_triIndexes->clear(true); else resize(lastTri); m_bBox.setValidity(false); notifyGeometryUpdate(); } } if (newSubMesh->size()) { newSubMesh->setName(getName()+QString(".part")); newSubMesh->resize(newSubMesh->size()); newSubMesh->setDisplay(getDisplay()); newSubMesh->showColors(colorsShown()); newSubMesh->showNormals(normalsShown()); newSubMesh->showMaterials(materialsShown()); newSubMesh->showSF(sfShown()); newSubMesh->enableStippling(stipplingEnabled()); newSubMesh->showWired(isShownAsWire()); } else { assert(false); delete newSubMesh; newSubMesh = 0; } return newSubMesh; }
bool ccSphere::buildUp() { if (m_drawPrecision<4) return false; const unsigned steps = m_drawPrecision; //vertices ccPointCloud* verts = vertices(); assert(verts); //vertices unsigned count = steps*(steps-1)+2; //faces unsigned faces = steps*((steps-2)*2+2); if (!init(count,true,faces,0)) { ccLog::Error("[ccSphere::buildUp] Not enough memory"); return false; } //2 first points: poles verts->addPoint(CCVector3(0,0,m_radius)); verts->addNorm(CCVector3(0,0,1)); verts->addPoint(CCVector3(0,0,-m_radius)); verts->addNorm(CCVector3(0,0,-1)); //then, angular sweep PointCoordinateType angle_rad_step = static_cast<PointCoordinateType>(M_PI)/static_cast<PointCoordinateType>(steps); CCVector3 N0,N,P; { for (unsigned j=1; j<steps; ++j) { PointCoordinateType theta = static_cast<PointCoordinateType>(j) * angle_rad_step; PointCoordinateType cos_theta = cos(theta); PointCoordinateType sin_theta = sin(theta); N0.x = sin_theta; N0.y = 0; N0.z = cos_theta; for (unsigned i=0; i<steps; ++i) { PointCoordinateType phi = static_cast<PointCoordinateType>(2*i) * angle_rad_step; PointCoordinateType cos_phi = cos(phi); PointCoordinateType sin_phi = sin(phi); N.x = N0.x*cos_phi; N.y = N0.x*sin_phi; N.z = N0.z; N.normalize(); P = N * m_radius; verts->addPoint(P); verts->addNorm(N); } } } //faces { assert(m_triVertIndexes); //north pole { for (unsigned i=0; i<steps; ++i) { unsigned A = 2+i; unsigned B = (i+1<steps ? A+1 : 2); addTriangle(A,B,0); } } //slices for (unsigned j=1; j+1<steps; ++j) { unsigned shift = 2+(j-1)*steps; for (unsigned i=0; i<steps; ++i) { unsigned A = shift+i; unsigned B = (i+1<steps ? A+1 : shift); assert(B<count); addTriangle(A,A+steps,B); addTriangle(B+steps,B,A+steps); } } //south pole { unsigned shift = 2+(steps-2)*steps; for (unsigned i=0; i<steps; ++i) { unsigned A = shift+i; unsigned B = (i+1<steps ? A+1 : shift); assert(B<count); addTriangle(A,1,B); } } } notifyGeometryUpdate(); showNormals(true); return true; }