ccSubMesh::ccSubMesh(ccMesh* parentMesh) : ccGenericMesh("Sub-mesh") , m_associatedMesh(parentMesh) , m_triIndexes(new ReferencesContainer()) , m_globalIterator(0) { m_triIndexes->link(); showColors(parentMesh ? parentMesh->colorsShown() : true); showNormals(parentMesh ? parentMesh->normalsShown() : true); showSF(parentMesh ? parentMesh->sfShown() : true); }
ccSubMesh::ccSubMesh(ccMesh* parentMesh) : ccGenericMesh("Sub-mesh") , m_associatedMesh(0) , m_triIndexes(new ReferencesContainer()) , m_globalIterator(0) { m_triIndexes->link(); setAssociatedMesh(parentMesh); //must be called so as to set the right dependency! showColors(parentMesh ? parentMesh->colorsShown() : true); showNormals(parentMesh ? parentMesh->normalsShown() : true); showSF(parentMesh ? parentMesh->sfShown() : true); }
ccGenericPrimitive::ccGenericPrimitive(QString name/*=QString()*/, const ccGLMatrix* transMat /*= 0*/) : ccMesh(new ccPointCloud("vertices")) , m_drawPrecision(0) { setName(name); showNormals(true); ccPointCloud* vert = vertices(); assert(vert); addChild(vert); vert->setEnabled(false); if (transMat) m_transformation = *transMat; }
ccDrawableObject::ccDrawableObject() { setVisible(true); setSelected(false); showColors(false); showNormals(false); showSF(false); lockVisibility(false); showNameIn3D(false); m_currentDisplay=0; enableTempColor(false); setTempColor(ccColor::white,false); razGLTransformation(); }
ccGenericPrimitive::ccGenericPrimitive(QString name/*=QString()*/, const ccGLMatrix* transMat/*=0*/) : ccMesh(new ccPointCloud("vertices")) , m_drawPrecision(0) { setName(name); showNormals(true); ccPointCloud* vert = vertices(); assert(vert); addChild(vert); vert->setEnabled(false); //we don't want the user to transform the vertices for instance (as they are only temporary) vert->setLocked(true); if (transMat) m_transformation = *transMat; }
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,0.0,m_radius)); verts->addNorm(0.0,0.0,1.0); verts->addPoint(CCVector3(0.0,0.0,-m_radius)); verts->addNorm(0.0,0.0,-1.0); //then, angular sweep float angle_rad_step = M_PI/(float)steps; CCVector3 N0,N,P; { for (unsigned j=1;j<steps;++j) { float theta = (float)j * angle_rad_step; float cos_theta = cos(theta); float sin_theta = sin(theta); N0.x = sin_theta; N0.y = 0; N0.z = cos_theta; for (unsigned i=0;i<steps;++i) { float phi = (float)i * 2.0f * angle_rad_step; float cos_phi = cos(phi); float 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.u); } } } //faces { assert(m_triIndexes); //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); } } } updateModificationTime(); showNormals(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 ccGenericMesh::computeNormals() { if (!m_associatedCloud || !m_associatedCloud->isA(CC_POINT_CLOUD)) //TODO return false; unsigned triCount = size(); if (triCount==0) { ccLog::Error("[ccGenericMesh::computeNormals] Empty mesh!"); return false; } unsigned vertCount=m_associatedCloud->size(); if (vertCount<3) { ccLog::Error("[ccGenericMesh::computeNormals] Not enough vertices! (<3)"); return false; } ccPointCloud* cloud = static_cast<ccPointCloud*>(m_associatedCloud); //we instantiate a temporary structure to store each vertex normal (uncompressed) NormsTableType* theNorms = new NormsTableType; if (!theNorms->reserve(vertCount)) { theNorms->release(); return false; } theNorms->fill(0); //allocate compressed normals array on vertices cloud bool normalsWereAllocated = cloud->hasNormals(); if (!normalsWereAllocated && !cloud->resizeTheNormsTable()) { theNorms->release(); return false; } //for each triangle placeIteratorAtBegining(); { for (unsigned i=0; i<triCount; ++i) { CCLib::TriangleSummitsIndexes* tsi = getNextTriangleIndexes(); assert(tsi->i1<vertCount && tsi->i2<vertCount && tsi->i3<vertCount); const CCVector3 *A = cloud->getPoint(tsi->i1); const CCVector3 *B = cloud->getPoint(tsi->i2); const CCVector3 *C = cloud->getPoint(tsi->i3); //compute face normal (right hand rule) CCVector3 N = (*B-*A).cross(*C-*A); //N.normalize(); //DGM: no normalization = weighting by surface! //we add this normal to all triangle vertices PointCoordinateType* N1 = theNorms->getValue(tsi->i1); CCVector3::vadd(N1,N.u,N1); PointCoordinateType* N2 = theNorms->getValue(tsi->i2); CCVector3::vadd(N2,N.u,N2); PointCoordinateType* N3 = theNorms->getValue(tsi->i3); CCVector3::vadd(N3,N.u,N3); } } //for each vertex { for (unsigned i=0; i<vertCount; i++) { PointCoordinateType* N = theNorms->getValue(i); CCVector3::vnormalize(N); cloud->setPointNormal(i,N); theNorms->forwardIterator(); } } showNormals(true); if (!normalsWereAllocated) cloud->showNormals(true); //theNorms->clear(); theNorms->release(); theNorms=0; return true; }
void ccDrawableObject::toggleNormals() { showNormals(!normalsShown()); }
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; }