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; }
void ccGenericMesh::showNormals(bool state) { showTriNorms(state); ccHObject::showNormals(state); }
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; }