void CALLBACK Tesselator::combineCallback( GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, void* userData ) { Tesselator *tess = static_cast<Tesselator*>(userData); tess->_indices.push_back(tess->_indices.size()); tess->_vertices.push_back( TVec3d( coords[0], coords[1], coords[2] ) ); if (!tess->_texCoordsLists.empty()) { for (std::vector<TVec2f>& texcords : tess->_texCoordsLists) { if (texcords.empty()) { continue; } TVec2f newTexCoord(0,0); for (int i = 0; i < 4; i++) { if (vertex_data[i] != nullptr) { unsigned int vertexIndex = *reinterpret_cast<unsigned int*>(vertex_data[i]); newTexCoord = newTexCoord + weight[i] * texcords.at(vertexIndex); } } texcords.push_back(newTexCoord); assert(texcords.size() == tess->_vertices.size()); } } *outData = &tess->_indices.back(); }
TVec3d Polygon::computeNormal( void ) { if ( !_exteriorRing ) return TVec3d(); TVec3d normal = _exteriorRing->computeNormal(); return _negNormal ? -normal : normal; }
//==========================================================================* // Calculate Center and ToRight //--------------------------------------------------------------------------* void TTrackDescription::NormalizeDir( const tTrackSeg* Seg, double ToStart, double& T, TVec3d& Point, TVec3d& Normale) const { T = ToStart / Seg->length; double Zl = Seg->vertex[TR_SL].z + (Seg->vertex[TR_EL].z - Seg->vertex[TR_SL].z) * T; double Zr = Seg->vertex[TR_SR].z + (Seg->vertex[TR_ER].z - Seg->vertex[TR_SR].z) * T; if(Seg->type == TR_STR) { TVec3d Start = (TVec3d(Seg->vertex[TR_SL]) + TVec3d(Seg->vertex[TR_SR])) / 2; TVec3d End = (TVec3d(Seg->vertex[TR_EL]) + TVec3d(Seg->vertex[TR_ER])) / 2; Point = Start + (End - Start) * T; Normale = -TVec3d(Seg->rgtSideNormal); Normale.z = (Zr - Zl) / Seg->width; } else { double VZ = Seg->type == TR_LFT ? 1 : -1; double DeltaAngle = VZ * ToStart / Seg->radius; double Ang = Seg->angle[TR_ZS] - PI / 2 + DeltaAngle; double Cos = cos(Ang); double CosRad = VZ * Cos * Seg->radius; double Sin = sin(Ang); double SinRad = VZ * Sin * Seg->radius; Point = TVec3d(Seg->center.x + CosRad, Seg->center.y + SinRad, (Zl + Zr) / 2); Normale = TVec3d(Cos, Sin, (Zr - Zl) / Seg->width); } }
TVec3d LinearRing::computeNormal( void ) const { unsigned int len = size(); if ( len < 3 ) return TVec3d(); // Tampieri, F. 1992. Newell's method for computing the plane equation of a polygon. In Graphics Gems III, pp.231-232. TVec3d n( 0., 0., 0. ); for ( unsigned int i = 0; i < len; i++ ) { const TVec3d& current = _vertices[i]; const TVec3d& next = _vertices[ ( i + 1 ) % len]; n.x += ( current.y - next.y ) * ( current.z + next.z ); n.y += ( current.z - next.z ) * ( current.x + next.x ); n.z += ( current.x - next.x ) * ( current.y + next.y ); } return n.normal(); }
bool Tessellation(int& OutputVertNum, int& OutputIndiceNum) { if (ExtRingCoords == NULL) { return false; } #ifdef _DEBUG //test std::cout<<"EXT"<<std::endl; std::cout<<ExtRingVertNum<<std::endl; for (int i = 0; i < ExtRingVertNum; i++) { std::cout<<ExtRingCoords[i][0]<<ExtRingCoords[i][1]<<ExtRingCoords[i][2]<<std::endl; } std::cout<<"INT"<<std::endl; std::cout<<IntRingCoordsNum.size()<<std::endl; std::vector<int>::iterator itr = IntRingCoordsNum.begin(); std::vector<Vec3*>::iterator itr2 = IntRingCoords.begin(); for (;itr != IntRingCoordsNum.end(); itr++, itr2++) { std::cout<<*itr<<std::endl; for (int i = 0 ; i <*itr; i ++ ) { std::cout<<(*itr2)[i][0]<<(*itr2)[i][1]<<(*itr2)[i][2]<<std::endl; } } std::cout<<"good1"<<std::endl; #endif int IntRingNum = IntRingCoords.size(); //calculate the normal Vec3 pNorm; pNorm[0] = 0.0; pNorm[1] = 0.0; pNorm[2] = 0.0; Vec3 lVert; lVert[0] = ExtRingCoords[ExtRingVertNum - 1][0]; lVert[1] = ExtRingCoords[ExtRingVertNum - 1][1]; lVert[2] = ExtRingCoords[ExtRingVertNum - 1][2]; for (int i = 0 ; i < ExtRingVertNum; i++) { Vec3 pStep; pStep[0] = (lVert[2] + ExtRingCoords[i][2]) * (lVert[1] - ExtRingCoords[i][1]); pStep[1] = (lVert[0] + ExtRingCoords[i][0]) * (lVert[2] - ExtRingCoords[i][2]); pStep[2] = (lVert[1] + ExtRingCoords[i][1]) * (lVert[0] - ExtRingCoords[i][0]); pNorm[0] = pNorm[0] + pStep[0]; pNorm[1] = pNorm[1] + pStep[1]; pNorm[2] = pNorm[2] + pStep[2]; lVert[0] = ExtRingCoords[i][0]; lVert[1] = ExtRingCoords[i][1]; lVert[2] = ExtRingCoords[i][2]; } #ifdef _DEBUG //test std::cout<<"good2"<<std::endl; #endif //do tessellation //verts number int VertNum = ExtRingVertNum; for (int i = 0; i < IntRingCoordsNum.size(); i++) VertNum += IntRingCoordsNum[i]; // #ifdef _DEBUG //test std::cout<<"good2.1"<<std::endl; std::cout<<"VertNum: "<<VertNum<<std::endl; std::cout<<pNorm[0]<<pNorm[1]<<pNorm[2]<<std::endl; #endif tess.init(VertNum, TVec3d(pNorm[0], pNorm[1], pNorm[2])); std::vector<TVec3d> ring; std::vector<TVec2f> tag;//no use //add ExtierRing for (int i = 0; i < ExtRingVertNum; i++) { TVec3d vert(ExtRingCoords[i][0], ExtRingCoords[i][1], ExtRingCoords[i][2]); ring.push_back(vert); } #ifdef _DEBUG //test std::cout<<"good2.2"<<std::endl; std::cout<<ring.size()<<std::endl; #endif tess.addContour(ring, tag); ring.clear(); //add InteriorRings for (int i = 0; i < IntRingNum; i++) { for (int j = 0 ; j < IntRingCoordsNum[i]; j++) { TVec3d vert(IntRingCoords[i][j][0], IntRingCoords[i][j][1], IntRingCoords[i][j][2]); ring.push_back(vert); } tess.addContour(ring, tag); ring.clear(); } #ifdef _DEBUG //test std::cout<<"good2.3"<<std::endl; #endif tess.compute(); //return results if (tess.getIndices().size() == 0) { return false; } #ifdef _DEBUG //test std::cout<<"good3"<<std::endl; #endif //return coordsSAT OutputVertNum = tess.getVertices().size(); OutputIndiceNum = tess.getIndices().size()/3; // { delete[] ExtRingCoords; ExtRingCoords = NULL; std::vector<Vec3*>::iterator itr = IntRingCoords.begin(); for (; itr != IntRingCoords.end(); itr++) { delete[] *itr; *itr = NULL; } } #ifdef _DEBUG //test std::cout<<"good4"<<std::endl; #endif return true; }
//==========================================================================* // Utility to normalize a 3D vector in 2D projection //--------------------------------------------------------------------------* TVec3d TUtils::VecNormXY( const TVec3d& v ) { return TVec3d(-v.y, v.x, v.z); }