bool SaveGridHierarchyTransformed(MultiGrid& mg, ISubsetHandler& sh, const char* filename, number offset) { PROFILE_FUNC_GROUP("grid"); APosition aPos; // uses auto-attach Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true); // copy the existing position to aPos. We take care of dimension differences. // Note: if the method was implemented for domains, this could be implemented // in a nicer way. if(mg.has_vertex_attachment(aPosition)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos); else if(mg.has_vertex_attachment(aPosition2)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos); else if(mg.has_vertex_attachment(aPosition1)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos); // iterate through all vertices and apply an offset depending on their level. for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){ for(VertexIterator iter = mg.begin<Vertex>(lvl); iter != mg.end<Vertex>(lvl); ++iter) { aaPos[*iter].z() += (number)lvl * offset; } } // finally save the grid bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos); // clean up mg.detach_from_vertices(aPos); return writeSuccess; }
void CopyGridLevel(MultiGrid& srcMG, Grid& destGrid, ISubsetHandler& srcSH, ISubsetHandler& destSH, int lvl, TAPos aPos) { Grid::VertexAttachmentAccessor<TAPos> aaPos(destGrid, aPos); Grid::VertexAttachmentAccessor<TAPos> aaSrcPos(srcMG, aPos); GridObjectCollection goc = srcMG.get_grid_objects(); AVertex aNewVrt; srcMG.attach_to_vertices(aNewVrt); Grid::VertexAttachmentAccessor<AVertex> aaNewVrt(srcMG, aNewVrt); for(int si = destSH.num_subsets(); si < srcSH.num_subsets(); ++si) { destSH.subset_info(si) = srcSH.subset_info(si); } for(VertexIterator vrtIter = goc.begin<Vertex>(lvl); vrtIter != goc.end<Vertex>(lvl); ++vrtIter) { Vertex* srcVrt = *vrtIter; Vertex* destVrt = *destGrid.create_by_cloning(srcVrt); aaNewVrt[srcVrt] = destVrt; aaPos[destVrt] = aaSrcPos[srcVrt]; destSH.assign_subset(destVrt, srcSH.get_subset_index(srcVrt)); } CopyGridLevelElements<Edge>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt); CopyGridLevelElements<Face>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt); CopyGridLevelElements<Volume>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt); srcMG.detach_from_vertices(aNewVrt); }
void RemoveDoubles(Grid& grid, const TVrtIterator& iterBegin, const TVrtIterator& iterEnd, Attachment<MathVector<dim> >& aPos, number threshold) { if(!grid.has_vertex_attachment(aPos)) return; typedef Attachment<MathVector<dim> > attachment_type; Grid::VertexAttachmentAccessor<attachment_type> aaPos(grid, aPos); RemoveDoubles<dim>(grid, iterBegin, iterEnd, aaPos, threshold); }
bool CalculateVertexNormals(Grid& grid, APosition& aPos, ANormal& aNorm) { if(!grid.has_attachment<Vertex>(aPos)) return false; if(!grid.has_attachment<Vertex>(aNorm)) grid.attach_to<Vertex>(aNorm); Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos); Grid::VertexAttachmentAccessor<ANormal> aaNorm(grid, aNorm); return CalculateVertexNormals(grid, aaPos, aaNorm); }
bool SaveSurfaceViewTransformed(MultiGrid& mg, const SurfaceView& sv, const char* filename, number offset) { PROFILE_FUNC_GROUP("grid"); APosition aPos; // uses auto-attach Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true); // copy the existing position to aPos. We take care of dimension differences. // Note: if the method was implemented for domains, this could be implemented // in a nicer way. if(mg.has_vertex_attachment(aPosition)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos); else if(mg.has_vertex_attachment(aPosition2)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos); else if(mg.has_vertex_attachment(aPosition1)) ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos); // iterate through all vertices and apply an offset depending on their level. for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){ for(VertexIterator iter = mg.begin<Vertex>(lvl); iter != mg.end<Vertex>(lvl); ++iter) { aaPos[*iter].z() += (number)lvl * offset; } } // create a subset handler which holds different subsets for the different interface types SubsetHandler sh(mg); AssignSubsetsBySurfaceViewState<Vertex>(sh, sv, mg); AssignSubsetsBySurfaceViewState<Edge>(sh, sv, mg); AssignSubsetsBySurfaceViewState<Face>(sh, sv, mg); AssignSubsetsBySurfaceViewState<Volume>(sh, sv, mg); AssignSubsetColors(sh); EraseEmptySubsets(sh); // finally save the grid bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos); // clean up mg.detach_from_vertices(aPos); return writeSuccess; }
/// Creates an Icosahedron void GenerateIcosahedron(Grid& grid, const vector3& center, number radius, AVector3& aPos) { const number A = 0.85065080835204; const number B = 0.525731112119134; // create the vertices const number coords[12][3] = { {-B, A, 0}, {0, B, A}, {B, A, 0}, {0, B, -A}, {-A, 0, B}, {A, 0, B}, {A, 0, -B}, {-A, 0, -B}, {-B, -A, 0}, {0, -B, A}, {B, -A, 0}, {0, -B, -A}}; const int inds[20][3] = { {0, 1, 2}, {0, 2, 3}, {3, 7, 0}, {7, 4, 0}, {0, 4, 1}, {1, 5, 2}, {5, 6, 2}, {2, 6, 3}, {4, 9, 1}, {1, 9, 5}, {7, 3, 11}, {3, 6, 11}, {11, 8, 7}, {7, 8, 4}, {8, 9, 4}, {9, 10, 5}, {10, 6, 5}, {10, 11, 6}, {8, 10, 9}, {8, 11, 10}}; Vertex* vrts[12]; if(!grid.has_vertex_attachment(aPos)) grid.attach_to_vertices(aPos); Grid::AttachmentAccessor<Vertex, AVector3> aaPos(grid, aPos); for(size_t i = 0; i < 12; ++i){ vrts[i] = *grid.create<RegularVertex>(); aaPos[vrts[i]] = vector3(coords[i][0], coords[i][1], coords[i][2]); VecScaleAdd(aaPos[vrts[i]], 1.0, center, radius, aaPos[vrts[i]]); } // construct triangles for(size_t i = 0; i < 20; ++i){ grid.create<Triangle>(TriangleDescriptor(vrts[inds[i][0]], vrts[inds[i][1]], vrts[inds[i][2]])); } }
bool SaveGridToNCDF(Grid& grid, const char* filename, ISubsetHandler* pSH, APosition aPos) { // open the file to which we'll write ofstream out(filename); if(!out) return false; // access subset-handler if(!pSH){ UG_LOG("ERROR: SubsetHandler required for NCDF (Exodus) export.\n"); return false; } ISubsetHandler& sh = *pSH; // access the position attachment if(!grid.has_vertex_attachment(aPos)) return false; if(grid.num_volumes() != grid.num<Tetrahedron>()){ UG_LOG("Saving grid to EXODUS-format.\n" << " WARNING: only Tetrahedrons exported in the moment.\n"); } Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos); // assign vertex indices AInt aInt; grid.attach_to_vertices(aInt); Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt); AssignIndices(grid.vertices_begin(), grid.vertices_end(), aaInt, 1); // write exodus header int var4 = 4; out << "netcdf object {" << endl; out << "dimensions:" << endl; out << "\tlen_string = 33 ;" << endl; out << "\tlen_line = 81 ;" << endl; out << "\tfour = " << var4 << " ;" << endl; out << "\ttime_step = UNLIMITED ;" << endl; out << "\tnum_dim = 3 ;" << endl; out << "\tnum_nodes = " << grid.num_vertices() << " ;" << endl; out << "\tnum_elem = " << grid.num<Tetrahedron>() << " ;" << endl; out << "\tnum_el_blk = " << sh.num_subsets() << " ;" << endl; for(int i = 0; i < sh.num_subsets(); ++i){ GridObjectCollection goc = sh.get_grid_objects_in_subset(i); out << "\tnum_el_in_blk" << i+1 << " = " << goc.num<Tetrahedron>() << " ;" << endl; out << "\tnum_nod_per_el" << i+1 << " = 4 ;" << endl; } out << "\tnum_qa_rec = 1 ;" << endl; // write variables out << endl; out << "variables:" << endl; out << "\tdouble time_whole(time_step) ;" << endl; out << "\tint eb_status(num_el_blk) ;" << endl; out << "\tint eb_prop1(num_el_blk) ;" << endl; out << "\t\teb_prop1:name = \"ID\" ;" << endl; for(int i = 0; i < sh.num_subsets(); ++i){ out << "\tint connect" << i+1 << "(num_el_in_blk" << i+1 << ", num_nod_per_el" << i+1 << ") ;" << endl; out << "\t\tconnect" << i+1 << ":elem_type = \"TETRA4\" ;" << endl; } out << "\tdouble coord(num_dim, num_nodes) ;" << endl; out << "\tchar qa_records(num_qa_rec, four, len_string) ;" << endl; out << "\tchar coor_names(num_dim, len_string) ;" << endl; out << "\tint elem_map(num_elem) ;" << endl; out << "\tint elem_num_map(num_elem) ;" << endl; out << "\tint node_num_map(num_nodes) ;" << endl; out << "// global attributes:" << endl; out << "\t:api_version = 4.01f ;" << endl; out << "\t:version = 3.01f ;" << endl; out << "\t:floating_point_word_size = " << sizeof(number) << " ;" << endl; out << "\t:file_size = 0 ;" << endl; out << "\t:title = \"Exported from lib_grid.\" ;" << endl; // write data out << endl; out << "data:" << endl; out << "eb_status = "; for(int i = 0; i < sh.num_subsets(); ++i){ out << "1"; if(i + 1 < sh.num_subsets()) out << ", "; } out << " ;" << endl << endl; out << "eb_prop1 = "; for(int i = 0; i < sh.num_subsets(); ++i){ out << i+1; if(i + 1 < sh.num_subsets()) out << ", "; } out << " ;" << endl << endl; // write elements for(int i = 0; i < sh.num_subsets(); ++i){ // get the goc for this subset GridObjectCollection goc = sh.get_grid_objects_in_subset(i); out << "connect" << i+1 << " =" << endl; for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){ for(TetrahedronIterator iter = goc.begin<Tetrahedron>(lvl); iter != goc.end<Tetrahedron>(lvl); ++iter) { // last comma in each row if(iter != goc.begin<Tetrahedron>(lvl)) out << "," << endl; Tetrahedron* tet = *iter; out << " "; out << aaInt[tet->vertex(0)] << ", "; out << aaInt[tet->vertex(1)] << ", "; out << aaInt[tet->vertex(2)] << ", "; out << aaInt[tet->vertex(3)]; } } out << " ;" << endl << endl; } // write coords // x out << "coord =" << endl << " "; size_t endlCounter = 1; for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); ++iter, ++endlCounter) { if(endlCounter > 5){ endlCounter = 1; out << endl << " "; } out << " " << aaPos[*iter].x() << ","; } // y for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); ++iter, ++endlCounter) { if(endlCounter > 5){ endlCounter = 1; out << endl << " "; } out << " " << aaPos[*iter].y() << ","; } // z for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); ++iter, ++endlCounter) { if(iter != grid.vertices_begin()){ out << ","; if(endlCounter > 5){ endlCounter = 1; out << endl << " "; } } out << " " << aaPos[*iter].z(); } out << " ;" << endl << endl; // write qa_records out << "qa_records =" << endl; out << " \"lib_grid\"," << endl; out << " \"...\"," << endl; out << " \"...\"," << endl; out << " \"...\" ;" << endl; // write coor_names out << endl; out << "coor_names =" << endl; out << " \"x\"," << endl; out << " \"y\"," << endl; out << " \"z\" ;" << endl; // write elem_map out << endl; out << "elem_map = "; endlCounter = 1; for(size_t i = 0; i < grid.num<Tetrahedron>(); ++i, ++endlCounter) { out << i+1; if(i+1 < grid.num<Tetrahedron>()){ out << ", "; if(endlCounter > 4){ endlCounter = 0; out << endl << " "; } } } out << " ;" << endl; // write elem_num_map out << endl; out << "elem_num_map = "; endlCounter = 1; for(size_t i = 0; i < grid.num<Tetrahedron>(); ++i, ++endlCounter) { out << i+1; if(i+1 < grid.num<Tetrahedron>()){ out << ", "; if(endlCounter > 4){ endlCounter = 0; out << endl << " "; } } } out << " ;" << endl; // write node_num_map out << endl; out << "node_num_map = "; endlCounter = 1; for(size_t i = 0; i < grid.num<Vertex>(); ++i, ++endlCounter) { out << i+1; if(i+1 < grid.num<Vertex>()){ out << ", "; if(endlCounter > 4){ endlCounter = 0; out << endl << " "; } } } out << " ;" << endl; // close object out << "}" << endl; // remove vertex indices grid.detach_from_vertices(aInt); // done return true; }
/****************************************************************************** * Render the current scene * uses the global variables from the parser *****************************************************************************/ int ntlWorld::renderScene( void ) { #ifndef ELBEEM_PLUGIN char nrStr[5]; // nr conversion std::ostringstream outfn_conv(""); // converted ppm with other suffix ntlRenderGlobals *glob; // storage for global rendering parameters myTime_t timeStart,totalStart,timeEnd; // measure user running time myTime_t rendStart,rendEnd; // measure user rendering time glob = mpGlob; // deactivate for all with index!=0 if((glob_mpactive)&&(glob_mpindex>0)) return(0); /* check if picture already exists... */ if(!glob->getSingleFrameMode() ) { snprintf(nrStr, 5, "%04d", glob->getAniCount() ); if(glob_mpactive) { outfn_conv << glob->getOutFilename() <<"_"<<glob_mpindex<<"_" << nrStr << ".png"; /// DEBUG! } else { // ORG outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png"; } //if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) { if(mpGlob->getFrameSkip()) { struct stat statBuf; if(stat(outfn_conv.str().c_str(),&statBuf) == 0) { errorOut("ntlWorld::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); glob->setAniCount( glob->getAniCount() +1 ); return(2); } } // RAY mode } else { // single frame rendering, overwrite if necessary... outfn_conv << glob->getSingleFrameFilename(); } /* start program */ timeStart = getTime(); /* build scene geometry, calls buildScene(t,false) */ glob->getRenderScene()->prepareScene(mSimulationTime); /* start program */ totalStart = getTime(); /* view parameters are currently not animated */ /* calculate rays through projection plane */ ntlVec3Gfx direction = glob->getLookat() - glob->getEye(); /* calculate width of screen using perpendicular triangle diven by * viewing direction and screen plane */ gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI ); /* calculate vector orthogonal to up and viewing direction */ ntlVec3Gfx upVec = glob->getUpVec(); ntlVec3Gfx rightVec( cross(upVec,direction) ); normalize(rightVec); /* calculate screen plane up vector, perpendicular to viewdir and right vec */ upVec = ntlVec3Gfx( cross(rightVec,direction) ); normalize(upVec); /* check if vectors are valid */ if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) { errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec); return(1); } /* length from center to border of screen plane */ rightVec *= (screenWidth*glob->getAspect() * -1.0); upVec *= (screenWidth * -1.0); /* screen traversal variables */ ntlVec3Gfx screenPos; /* current position on virtual screen */ int Xres = glob->getResX(); /* X resolution */ int Yres = glob->getResY(); /* Y resolution */ ntlVec3Gfx rightStep = (rightVec/(Xres/2.0)); /* one step right for a pixel */ ntlVec3Gfx upStep = (upVec/(Yres/2.0)); /* one step up for a pixel */ /* anti alias init */ char showAAPic = 0; int aaDepth = glob->getAADepth(); int aaLength; if(aaDepth>=0) aaLength = (2<<aaDepth); else aaLength = 0; float aaSensRed = 0.1; float aaSensGreen = 0.1; float aaSensBlue = 0.1; int aaArrayX = aaLength*Xres+1; int aaArrayY = ( aaLength+1 ); ntlColor *aaCol = new ntlColor[ aaArrayX*aaArrayY ]; char *aaUse = new char[ aaArrayX*aaArrayY ]; /* picture storage */ int picX = Xres; int picY = Yres; if(showAAPic) { picX = Xres *aaLength+1; picY = Yres *aaLength+1; } ntlColor *finalPic = new ntlColor[picX * picY]; /* reset picture vars */ for(int j=0;j<aaArrayY;j++) { for(int i=0;i<aaArrayX;i++) { aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0); aaUse[j*aaArrayX+i] = 0; } } for(int j=0;j<picY;j++) { for(int i=0;i<picX;i++) { finalPic[j*picX+i] = ntlColor(0.0, 0.0, 0.0); } } /* loop over all y lines in screen, from bottom to top because * ppm format wants 0,0 top left */ rendStart = getTime(); glob->setCounterShades(0); glob->setCounterSceneInter(0); for (int scanline=Yres ; scanline > 0 ; --scanline) { debugOutInter( "ntlWorld::renderScene: Line "<<scanline<< " ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 ); screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres) - rightVec; /* loop over all pixels in line */ for (int sx=0 ; sx < Xres ; ++sx) { if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) { // DEBUG!!! glob->setDebugOut(10); } else glob->setDebugOut(0); /* compute ray from eye through current pixel into scene... */ ntlColor col; if(aaDepth<0) { ntlVec3Gfx dir(screenPos - glob->getEye()); ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); /* ...and trace it */ col = the_ray.shade(); } else { /* anti alias */ int ai,aj; /* position in grid */ int aOrg = sx*aaLength; /* grid offset x */ int currStep = aaLength; /* step size */ char colDiff = 1; /* do colors still differ too much? */ ntlColor minCol,maxCol; /* minimum and maximum Color Values */ minCol = ntlColor(1.0,1.0,1.0); maxCol = ntlColor(0.0,0.0,0.0); while((colDiff) && (currStep>0)) { colDiff = 0; for(aj = 0;aj<=aaLength;aj+= currStep) { for(ai = 0;ai<=aaLength;ai+= currStep) { /* shade pixel if not done */ if(aaUse[aj*aaArrayX +ai +aOrg] == 0) { aaUse[aj*aaArrayX +ai +aOrg] = 1; ntlVec3Gfx aaPos( screenPos + (rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) + (upStep * (aj- aaLength/2)/(gfxReal)aaLength ) ); ntlVec3Gfx dir(aaPos - glob->getEye()); ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); /* ...and trace it */ ntlColor newCol= the_ray.shade(); aaCol[aj*aaArrayX +ai +aOrg]= newCol; } /* not used? */ } } /* check color differences */ for(aj = 0;aj<aaLength;aj+= currStep) { for(ai = 0;ai<aaLength;ai+= currStep) { char thisColDiff = 0; if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } else if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } else if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } //colDiff =1; if(thisColDiff) { /* set diff flag */ colDiff = thisColDiff; for(int bj=aj;bj<=aj+currStep;bj++) { for(int bi=ai;bi<=ai+currStep;bi++) { if(aaUse[bj*aaArrayX +bi +aOrg]==2) { //if(showAAPic) aaUse[bj*aaArrayX +bi +aOrg] = 0; } } } } else { /* set all values */ ntlColor avgCol = ( aaCol[(aj+0 )*aaArrayX +(ai+0 ) +aOrg] + aaCol[(aj+0 )*aaArrayX +(ai+currStep) +aOrg] + aaCol[(aj+currStep)*aaArrayX +(ai+0 ) +aOrg] + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25; for(int bj=aj;bj<=aj+currStep;bj++) { for(int bi=ai;bi<=ai+currStep;bi++) { if(aaUse[bj*aaArrayX +bi +aOrg]==0) { aaCol[bj*aaArrayX +bi +aOrg] = avgCol; aaUse[bj*aaArrayX +bi +aOrg] = 2; } } } } /* smaller values set */ } } /* half step size */ currStep /= 2; } /* repeat until diff not too big */ /* get average color */ gfxReal colNum = 0.0; col = ntlColor(0.0, 0.0, 0.0); for(aj = 0;aj<=aaLength;aj++) { for(ai = 0;ai<=aaLength;ai++) { col += aaCol[aj*aaArrayX +ai +aOrg]; colNum += 1.0; } } col /= colNum; } /* mark pixels with debugging */ if( glob->getDebugOut() > 0) col = ntlColor(0,1,0); /* store pixel */ if(!showAAPic) { finalPic[(scanline-1)*picX+sx] = col; } screenPos += rightStep; } /* foreach x */ /* init aa array */ if(showAAPic) { for(int j=0;j<=aaArrayY-1;j++) { for(int i=0;i<=aaArrayX-1;i++) { if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0; } } } for(int i=0;i<aaArrayX;i++) { aaCol[(aaArrayY-1)*aaArrayX+i] = aaCol[0*aaArrayX+i]; aaUse[(aaArrayY-1)*aaArrayX+i] = aaUse[0*aaArrayX+i]; } for(int j=0;j<aaArrayY-1;j++) { for(int i=0;i<aaArrayX;i++) { aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0); aaUse[j*aaArrayX+i] = 0; } } } /* foreach y */ rendEnd = getTime(); /* write png file */ { int w = picX; int h = picY; unsigned rowbytes = w*4; unsigned char *screenbuf, **rows; screenbuf = (unsigned char*)malloc( h*rowbytes ); rows = (unsigned char**)malloc( h*sizeof(unsigned char*) ); unsigned char *filler = screenbuf; // cutoff color values 0..1 for(int j=0;j<h;j++) { for(int i=0;i<w;i++) { ntlColor col = finalPic[j*w+i]; for (unsigned int cc=0; cc<3; cc++) { if(col[cc] <= 0.0) col[cc] = 0.0; if(col[cc] >= 1.0) col[cc] = 1.0; } *filler = (unsigned char)( col[0]*255.0 ); filler++; *filler = (unsigned char)( col[1]*255.0 ); filler++; *filler = (unsigned char)( col[2]*255.0 ); filler++; *filler = (unsigned char)( 255.0 ); filler++; // alpha channel } } for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ]; writePng(outfn_conv.str().c_str(), rows, w, h); } // next frame glob->setAniCount( glob->getAniCount() +1 ); // done timeEnd = getTime(); char resout[1024]; snprintf(resout,1024, "NTL Done %s, frame %d/%d (took %s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1), getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(), glob->getCounterShades(), glob->getCounterSceneInter() ); debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 ); /* clean stuff up */ delete [] aaCol; delete [] aaUse; delete [] finalPic; glob->getRenderScene()->cleanupScene(); if(mpGlob->getSingleFrameMode() ) { debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); return 1; } #endif // ELBEEM_PLUGIN return 0; }
bool TriangleFill_SweepLine(Grid& grid, TIterator edgesBegin, TIterator edgesEnd, APosition& aPosVRT, AInt& aIntVRT, SubsetHandler* pSH, int newSubsetIndex) { if(!grid.has_vertex_attachment(aPosVRT)){ UG_LOG("position attachment missing in TriangleFill_SweepLine"); return false; } if(!grid.has_vertex_attachment(aIntVRT)){ UG_LOG("int attachment missing in TriangleFill_SweepLine"); return false; } Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPosVRT); Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aIntVRT); // set up the vertex and edge arrays and build some additional // information that is required when it comes to building the triangles. std::vector<Vertex*> vrtPtrs; std::vector<vector3> vrts; std::vector<int> edges; grid.begin_marking(); for(TIterator iter = edgesBegin; iter != edgesEnd; ++iter) { Edge* e = *iter; for(size_t i = 0; i < 2; ++i){ Vertex* vrt = e->vertex(i); if(!grid.is_marked(vrt)){ aaInt[vrt] = (int)vrts.size(); vrts.push_back(aaPos[vrt]); //vrts.push_back(vector2(aaPos[vrt].x(), aaPos[vrt].y())); vrtPtrs.push_back(vrt); grid.mark(vrt); } edges.push_back(aaInt[vrt]); } } grid.end_marking(); // now call the original implementation size_t numInitialEdges = edges.size(); std::vector<int> faces; if(TriangleFill_SweepLine(faces, vrts, edges)){ // now create the triangles for(size_t i = 0; i < faces.size(); i+=3){ Triangle* tri = *grid.create<Triangle>(TriangleDescriptor(vrtPtrs[faces[i]], vrtPtrs[faces[i + 1]], vrtPtrs[faces[i + 2]])); if(pSH){ pSH->assign_subset(tri, newSubsetIndex); } } return true; } else{ //DEBUG ONLY // create edges for(size_t i = numInitialEdges; i < edges.size(); i+=2){ Edge* e = *grid.create<RegularEdge>(EdgeDescriptor(vrtPtrs[edges[i]], vrtPtrs[edges[i+1]])); if(pSH){ pSH->assign_subset(e, newSubsetIndex); } } } return false; }
bool AdaptSurfaceGridToCylinder(Selector& selOut, Grid& grid, Vertex* vrtCenter, const vector3& normal, number radius, number rimSnapThreshold, AInt& aInt, APosition& aPos) { if(!grid.has_vertex_attachment(aPos)) { UG_THROW("Position attachment required!"); } Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos); if(rimSnapThreshold < 0) rimSnapThreshold = 0; if(rimSnapThreshold > (radius - SMALL)) rimSnapThreshold = radius - SMALL; const number smallRadius = radius - rimSnapThreshold; const number smallRadiusSq = smallRadius * smallRadius; const number largeRadius = radius + rimSnapThreshold; const number largeRadiusSq = largeRadius * largeRadius; // the cylinder geometry vector3 axis; VecNormalize(axis, normal); vector3 center = aaPos[vrtCenter]; // recursively select all vertices in the cylinder which can be reached from a // selected vertex by following an edge. Start with the given one. // We'll also select edges which connect inner with outer vertices. Note that // some vertices are considered rim-vertices (those with a distance between // smallRadius and largeRadius). Those are neither considered inner nor outer. Selector& sel = selOut; sel.clear(); sel.select(vrtCenter); stack<Vertex*> vrtStack; vrtStack.push(vrtCenter); Grid::edge_traits::secure_container edges; Grid::face_traits::secure_container faces; vector<Quadrilateral*> quads; while(!vrtStack.empty()) { Vertex* curVrt = vrtStack.top(); vrtStack.pop(); // we have to convert associated quadrilaterals to triangles. // Be careful not to alter the array of associated elements while we iterate // over it... quads.clear(); grid.associated_elements(faces, curVrt); for(size_t i = 0; i < faces.size(); ++i) { if(faces[i]->num_vertices() == 4) { Quadrilateral* q = dynamic_cast<Quadrilateral*>(faces[i]); if(q) quads.push_back(q); } } for(size_t i = 0; i < quads.size(); ++i) { Triangulate(grid, quads[i], &aaPos); } // now check whether edges leave the cylinder and mark them accordingly. // Perform projection of vertices to the cylinder rim for vertices which // lie in the threshold area. grid.associated_elements(edges, curVrt); for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge) { Edge* e = edges[i_edge]; Vertex* vrt = GetConnectedVertex(e, curVrt); if(sel.is_selected(vrt)) continue; vector3 p = aaPos[vrt]; vector3 proj; ProjectPointToRay(proj, p, center, axis); number distSq = VecDistanceSq(p, proj); if(distSq < smallRadiusSq) { sel.select(vrt); vrtStack.push(vrt); } else if(distSq < largeRadiusSq) { sel.select(vrt); // cut the ray from center through p with the cylinder hull to calculate // the new position of vrt. vector3 dir; VecSubtract(dir, p, center); number t0, t1; if(RayCylinderIntersection(t0, t1, center, dir, center, axis, radius)) VecScaleAdd(aaPos[vrt], 1., center, t1, dir); } else { // the edge will be refined later on sel.select(e); } } } // refine selected edges and use a special refinement callback, which places // new vertices on edges which intersect a cylinder on the cylinders hull. CylinderCutProjector refCallback(MakeGeometry3d(grid, aPos), center, axis, radius); Refine(grid, sel, aInt, &refCallback); // finally select all triangles which lie in the cylinder sel.clear(); vrtStack.push(vrtCenter); sel.select(vrtCenter); while(!vrtStack.empty()) { Vertex* curVrt = vrtStack.top(); vrtStack.pop(); grid.associated_elements(faces, curVrt); for(size_t i_face = 0; i_face < faces.size(); ++i_face) { Face* f = faces[i_face]; if(sel.is_selected(f)) continue; sel.select(f); for(size_t i = 0; i < f->num_vertices(); ++i) { Vertex* vrt = f->vertex(i); if(!sel.is_selected(vrt)) { number dist = DistancePointToRay(aaPos[vrt], center, axis); if(dist < (radius - SMALL)) { sel.select(vrt); vrtStack.push(vrt); } } } } } sel.clear<Vertex>(); return true; }