/** * \brief Create a new ass_font_t according to "desc" argument */ ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc) { int error; ass_font_t* fontp; ass_font_t font; fontp = ass_font_cache_find(desc); if (fontp) return fontp; font.library = library; font.ftlibrary = ftlibrary; font.n_faces = 0; font.desc.family = strdup(desc->family); font.desc.bold = desc->bold; font.desc.italic = desc->italic; font.scale_x = font.scale_y = 1.; font.v.x = font.v.y = 0; font.size = 0.; error = add_face(fc_priv, &font, 0); if (error == -1) { free(font.desc.family); return 0; } else return ass_font_cache_add(&font); }
/** * \brief Create a new ASS_Font according to "desc" argument */ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, FT_Library ftlibrary, ASS_FontSelector *fontsel, ASS_FontDesc *desc) { int error; ASS_Font *fontp; ASS_Font font; fontp = ass_cache_get(font_cache, desc); if (fontp) return fontp; font.library = library; font.ftlibrary = ftlibrary; font.shaper_priv = NULL; font.n_faces = 0; font.desc.family = strdup(desc->family); font.desc.bold = desc->bold; font.desc.italic = desc->italic; font.desc.vertical = desc->vertical; font.scale_x = font.scale_y = 1.; font.v.x = font.v.y = 0; font.size = 0.; error = add_face(fontsel, &font, 0); if (error == -1) { free(font.desc.family); return 0; } else return ass_cache_put(font_cache, &font.desc, &font); }
int get_coord(char *path, t_vertice **v, t_vertice_n **vn, t_face **f) { int fd; char *buff; char **sep; fd = open(path, O_RDONLY); if (fd == -1) exit(1); while ((buff = get_next_line(fd))) { sep = my_strtok(buff, " ", TOK_DELIM); if (sep && size_tab(sep) == 4) { if (!my_strcmp("v", sep[0])) add_vertice(v, atof(sep[1]), atof(sep[2]), atof(sep[3])); else if (!my_strcmp("f", sep[0])) add_face(f, sep[1], sep[2], sep[3]); else if (!my_strcmp("vn", sep[0])) add_vertice_norme(vn, atof(sep[1]), atof(sep[2]), atof(sep[3])); } } close(fd); return (1); }
obj_t::obj_t( const char * objname ) { // long name fullpath = realname( objname ); // model handle const char * shortname = strip_path_and_extension( objname ); name = copy_string( shortname ); // memory map file mmfile_t mm( fullpath ); index = 0; size = mm.size; data = mm.data; while ( index < size ) { strip_white_space(); switch( data[i] ) { case 'm': if ( check_name( "mtllib" ) ) consume_line(); break; case 'u': if ( check_name( "usemtl" ) ) consume_line(); break; case 'g': consume_line(); break; case '#': strip_white_space(); break; case 'v': if ( check_name( "vn" ) ) add_normal(); else if ( check_name( "vt" ) ) add_texcoord(); else if ( data[index+1] == ' ' ) add_vertex(); else core.warn( "obj_t: straggling v in objfile: %s", name ); break; case 'f': if ( data[index+1] == ' ' ) add_face(); break; case 's': default: ++index; break; } } }
static void triangulate(void) { FILE *files[2]; unsigned i, faces; unsigned a, b, c; int n; /* start qdelaunay */ if (popen2("qdelaunay Qt i", files) < 0) { perror("popen2"); exit(1); } /* send list of points */ if (fprintf(files[1], "2\n%u\n", n_nodes) < 0) { perror("fprintf"); exit(1); } for (i = 0; i != n_nodes; i++) { if (fprintf(files[1], "%d %d\n", node[i].x, node[i].y) < 0) { perror("fprintf"); exit(1); } } if (fclose(files[1]) < 0) { perror("fclose"); exit(1); } /* read list of faces (triangles) */ n = fscanf(files[0], "%u", &faces); if (n < 0) { perror("fscanf"); exit(1); } if (n != 1) { fprintf(stderr, "bad result (length)\n"); exit(1); } for (i = 0; i != faces; i++) { n = fscanf(files[0], "%u %u %u", &a, &b, &c); if (n < 0) { perror("fscanf"); exit(1); } if (n != 3) { fprintf(stderr, "bad result (face)\n"); exit(1); } add_face(a, b, c); } fclose(files[0]); }
Surface_mesh::Face Surface_mesh:: add_triangle(Vertex v0, Vertex v1, Vertex v2) { std::vector<Vertex> v(3); v[0] = v0; v[1] = v1; v[2] = v2; return add_face(v); }
Surface_mesh::Face Surface_mesh:: add_quad(Vertex v0, Vertex v1, Vertex v2, Vertex v3) { std::vector<Vertex> v(4); v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; return add_face(v); }
voxel_model::voxel_model(const Layer& layer, const LayerType& layer_type) : name_(layer_type.name), invalidated_(false), model_(1.0f), proto_model_(1.0f) { aabb_[0] = glm::vec3(std::numeric_limits<float>::max(),std::numeric_limits<float>::max(),std::numeric_limits<float>::max()); aabb_[1] = glm::vec3(std::numeric_limits<float>::min(),std::numeric_limits<float>::min(),std::numeric_limits<float>::min()); for(const std::pair<std::string, VoxelPos>& pivot : layer_type.pivots) { glm::vec3 point = glm::vec3(pivot.second) + glm::vec3(0.5f); pivots_.push_back(std::pair<std::string, glm::vec3>(pivot.first, point)); } vbo_id_.reset(new GLuint, [](GLuint* id){glDeleteBuffers(1, id); delete id;}); glGenBuffers(1, vbo_id_.get()); std::vector<GLfloat> varray[6]; std::vector<GLubyte> carray[6]; for(auto p : layer.map) { for(int n = FACE_LEFT; n != MAX_FACES; ++n) { glm::ivec3 pos = glm::ivec3(normal_vectors()[n]) + p.first; if(layer.map.find(pos) == layer.map.end()) { add_face(n, p, varray[n], carray[n]); } } } size_t total_size = 0; for(int n = FACE_LEFT; n != MAX_FACES; ++n) { vattrib_offsets_[n] = total_size; total_size += varray[n].size() * sizeof(GLfloat); num_vertices_[n] = varray[n].size() / 3; } for(int n = FACE_LEFT; n != MAX_FACES; ++n) { cattrib_offsets_[n] = total_size; total_size += carray[n].size() * sizeof(uint8_t); } glBindBuffer(GL_ARRAY_BUFFER, *vbo_id_); glBufferData(GL_ARRAY_BUFFER, total_size, NULL, GL_STATIC_DRAW); for(int n = FACE_LEFT; n != MAX_FACES; ++n) { glBufferSubData(GL_ARRAY_BUFFER, vattrib_offsets_[n], varray[n].size()*sizeof(GLfloat), &varray[n][0]); } for(int n = FACE_LEFT; n != MAX_FACES; ++n) { glBufferSubData(GL_ARRAY_BUFFER, cattrib_offsets_[n], carray[n].size()*sizeof(uint8_t), &carray[n][0]); } glBindBuffer(GL_ARRAY_BUFFER, 0); }
/** * \brief Create a new ASS_Font according to "desc" argument */ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, FT_Library ftlibrary, ASS_FontSelector *fontsel, ASS_FontDesc *desc) { ASS_Font *font; if (ass_cache_get(font_cache, desc, &font)) { if (font->desc.family) return font; ass_cache_dec_ref(font); return NULL; } if (!font) return NULL; font->library = library; font->ftlibrary = ftlibrary; font->shaper_priv = NULL; font->n_faces = 0; ASS_FontDesc *new_desc = ass_cache_key(font); font->desc.family = new_desc->family; font->desc.bold = desc->bold; font->desc.italic = desc->italic; font->desc.vertical = desc->vertical; font->scale_x = font->scale_y = 1.; font->v.x = font->v.y = 0; font->size = 0.; int error = add_face(fontsel, font, 0); if (error == -1) { font->desc.family = NULL; ass_cache_commit(font, 1); ass_cache_dec_ref(font); return NULL; } ass_cache_commit(font, 1); return font; }
void add_surface(const Chunk& chunk, meshmap_t& meshes, surface_t& surface, const Plane plane, const Side side) { uint_fast8_t ix, iy, iz; if(plane == Plane::XY) { ix = 0; iy = 2; iz = 1; } else if(plane == Plane::XZ) { ix = 0; iy = 1; iz = 2; } else // must be YZ { ix = 1; iy = 0; iz = 2; } u8vec3 xyz; for(xyz[1] = 0; xyz[1] < CHUNK_SIZE; ++xyz[1]) { generate_surface(chunk, surface, xyz, { ix, iy, iz }, static_cast<int_fast8_t>(side)); while(true) { const Rectangle rekt = yield_rectangle(surface); if(std::get<0>(rekt.key) == BlockType::none) { break; } mesh_vertex_coord_t v1; mesh_vertex_coord_t v2; mesh_vertex_coord_t v3; mesh_vertex_coord_t v4; uint_fast8_t y1 = xyz[1]; if(side == Side::top) { y1 += 1; } #define s(x) static_cast<mesh_vertex_coord_t::value_type>(x) v1[ix] = rekt.x; v1[iy] = y1; v1[iz] = rekt.z; v2[ix] = s(rekt.x + rekt.w); v2[iy] = y1; v2[iz] = rekt.z; v3[ix] = s(rekt.x + rekt.w); v3[iy] = y1; v3[iz] = s(rekt.z + rekt.h); v4[ix] = rekt.x; v4[iy] = y1; v4[iz] = s(rekt.z + rekt.h); #undef s mesh_t& mesh = meshes[rekt.key]; if((plane == Plane::XZ && side == Side::top) || (plane == Plane::XY && side == Side::bottom) || (plane == Plane::YZ && side == Side::bottom)) { add_face(mesh, v4, v3, v2, v1); } else { add_face(mesh, v1, v2, v3, v4); } } } }
void test_validity(Mesh& mesh) { typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits<Mesh>::edge_descriptor edge_descriptor; typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor; typedef typename boost::property_map<Mesh, CGAL::vertex_point_t>::type VPMap; VPMap vpmap = get(CGAL::vertex_point, mesh); vertex_descriptor vertices[4]; edge_descriptor edges[4]; vertices[0] = add_vertex(mesh); vertices[1] = add_vertex(mesh); vertices[2] = add_vertex(mesh); vertices[3] = add_vertex(mesh); put(vpmap, vertices[0], Point_3(0,0,0)); put(vpmap, vertices[1], Point_3(1,0,0)); put(vpmap, vertices[2], Point_3(1,1,0)); put(vpmap, vertices[3], Point_3(0,1,0)); edges[0] = add_edge(mesh); edges[1] = add_edge(mesh); edges[2] = add_edge(mesh); edges[3] = add_edge(mesh); assert(!CGAL::is_valid_halfedge_graph(mesh)); for(int i=0; i<4; ++i) { set_target(halfedge(edges[i], mesh), vertices[i], mesh); set_halfedge(vertices[i], halfedge(edges[i], mesh), mesh); } for(int i=0; i<4; ++i) set_target(opposite(halfedge(edges[i], mesh), mesh), vertices[(i+1)%4], mesh); for(int i=0; i<4; ++i) { set_next(halfedge(edges[(i+1)%4], mesh), halfedge(edges[i], mesh), mesh); set_next(opposite(halfedge(edges[i], mesh), mesh), opposite(halfedge(edges[(i+1)%4], mesh), mesh), mesh); } assert(CGAL::is_valid_halfedge_graph(mesh)); face_descriptor faces[1]; faces[0] = add_face(mesh); assert(!CGAL::is_valid_face_graph(mesh)); for(int i=0; i<4; ++i) { set_face(opposite(halfedge(edges[i], mesh), mesh), faces[0], mesh); } set_halfedge(faces[0], opposite(halfedge(edges[0], mesh), mesh), mesh); assert(CGAL::is_valid_face_graph(mesh)); assert(CGAL::is_valid_polygon_mesh(mesh)); Mesh dummy; vertices[0] = add_vertex(dummy); vertices[1] = add_vertex(dummy); edges[0] = add_edge(dummy); set_target(halfedge(edges[0], dummy), vertices[0], dummy); set_halfedge(vertices[0], halfedge(edges[0], dummy), dummy); set_target(opposite(halfedge(edges[0], dummy), dummy), vertices[1], dummy); set_halfedge(vertices[1], opposite(halfedge(edges[0], dummy), dummy), dummy); set_next(halfedge(edges[0], dummy), opposite(halfedge(edges[0], dummy), dummy), dummy); set_next(opposite(halfedge(edges[0], dummy), dummy), halfedge(edges[0], dummy), dummy); faces[0] = add_face(dummy); set_halfedge(faces[0], opposite(halfedge(edges[0], dummy), dummy), dummy); set_face(halfedge(edges[0], dummy), faces[0], dummy); set_face(opposite(halfedge(edges[0], dummy), dummy), faces[0], dummy); assert(CGAL::is_valid_face_graph(dummy)); assert(!CGAL::is_valid_polygon_mesh(dummy)); }
/** * \brief Get a glyph * \param ch character code **/ FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch, ass_hinting_t hinting) { int error; int index = 0; int i; FT_Glyph glyph; FT_Face face = 0; int flags = 0; if (ch < 0x20) return 0; if (font->n_faces == 0) return 0; for (i = 0; i < font->n_faces; ++i) { face = font->faces[i]; index = FT_Get_Char_Index(face, ch); if (index) break; } #ifdef HAVE_FONTCONFIG if (index == 0) { int face_idx; mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_GlyphNotFoundReselectingFont, ch, font->desc.family, font->desc.bold, font->desc.italic); face_idx = add_face(fontconfig_priv, font, ch); if (face_idx >= 0) { face = font->faces[face_idx]; index = FT_Get_Char_Index(face, ch); if (index == 0) { mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound, ch, font->desc.family, font->desc.bold, font->desc.italic); } } } #endif switch (hinting) { case ASS_HINTING_NONE: flags = FT_LOAD_NO_HINTING; break; case ASS_HINTING_LIGHT: flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; break; case ASS_HINTING_NORMAL: flags = FT_LOAD_FORCE_AUTOHINT; break; case ASS_HINTING_NATIVE: flags = 0; break; } error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags); if (error) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); return 0; } #if (FREETYPE_MAJOR > 2) || \ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || \ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10)) // FreeType >= 2.1.10 required if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) && (font->desc.italic > 55)) { FT_GlyphSlot_Oblique(face->glyph); } #endif error = FT_Get_Glyph(face->glyph, &glyph); if (error) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); return 0; } return glyph; }
// This routine assumes the sentinel points have already been added, and processes points in order GEODE_NEVER_INLINE static Ref<MutableTriangleTopology> deterministic_exact_delaunay(RawField<const Perturbed2,VertexId> X, const bool validate) { const int n = X.size()-3; const auto mesh = new_<MutableTriangleTopology>(); IntervalScope scope; // Initialize the mesh to a Delaunay triangle containing the sentinels at infinity. mesh->add_vertices(n+3); mesh->add_face(vec(VertexId(n+0),VertexId(n+1),VertexId(n+2))); if (self_check) { mesh->assert_consistent(); assert_delaunay("self check 0: ",mesh,X); } // The randomized incremental construction algorithm uses the history of the triangles // as the acceleration structure. Specifically, we maintain a BSP tree where the nodes // are edge tests (are we only the left or right of an edge) and the leaves are triangles. // There are two operations that modify this tree: // // 1. Split: A face is split into three by the insertion of an interior vertex. // 2. Flip: An edge is flipped, turning two triangles into two different triangles. // // The three starts out empty, since one triangle needs zero tests. Array<Node> bsp; // All BSP nodes including leaves bsp.preallocate(3*n); // The minimum number of possible BSP nodes Field<Vector<int,2>,FaceId> face_to_bsp; // Map from FaceId to up to two BSP leaf points (2*node+(right?0:1)) face_to_bsp.flat.preallocate(2*n+1); // The exact maximum number of faces face_to_bsp.flat.append_assuming_enough_space(vec(0,-1)); // By the time we call set_links, node 0 will be valid if (self_check) check_bsp(*mesh,bsp,face_to_bsp,X); // Allocate a stack to simulate recursion when flipping non-Delaunay edges. // Invariant: if edge is on the stack, the other edges of face(edge) are Delaunay. // Since halfedge ids change during edge flips in a corner mesh, we store half edges as directed vertex pairs. Array<Tuple<HalfedgeId,Vector<VertexId,2>>> stack; stack.preallocate(8); // Insert all vertices into the mesh in random order, maintaining the Delaunay property for (const auto i : range(n)) { const VertexId v(i); check_interrupts(); // Search through the BSP tree to find the containing triangle const auto f0 = bsp_search(bsp,X,v); const auto vs = mesh->vertices(f0); // Split the face by inserting the new vertex and update the BSP tree accordingly. mesh->split_face(f0,v); const auto e0 = mesh->halfedge(v), e1 = mesh->left(e0), e2 = mesh->right(e0); assert(mesh->dst(e0)==vs.x); const auto f1 = mesh->face(e1), f2 = mesh->face(e2); const int base = bsp.extend(3,uninit); set_links(bsp,face_to_bsp[f0],base); bsp[base+0] = Node(vec(v,vs.x),base+2,base+1); bsp[base+1] = Node(vec(v,vs.y),~f0.id,~f1.id); bsp[base+2] = Node(vec(v,vs.z),~f1.id,~f2.id); face_to_bsp[f0] = vec(2*(base+1)+0,-1); face_to_bsp.flat.append_assuming_enough_space(vec(2*(base+1)+1,2*(base+2)+0)); face_to_bsp.flat.append_assuming_enough_space(vec(2*(base+2)+1,-1)); if (self_check) { mesh->assert_consistent(); check_bsp(*mesh,bsp,face_to_bsp,X); } // Fix all non-Delaunay edges stack.copy(vec(tuple(mesh->next(e0),vec(vs.x,vs.y)), tuple(mesh->next(e1),vec(vs.y,vs.z)), tuple(mesh->next(e2),vec(vs.z,vs.x)))); if (self_check) assert_delaunay("self check 1: ",mesh,X,Tuple<>(),true); while (stack.size()) { const auto evs = stack.pop(); auto e = mesh->vertices(evs.x)==evs.y ? evs.x : mesh->halfedge(evs.y.x,evs.y.y); if (e.valid() && !is_delaunay(*mesh,X,e)) { // Our mesh is linearly embedded in the plane, so edge flips are always safe assert(mesh->is_flip_safe(e)); e = mesh->unsafe_flip_edge(e); GEODE_ASSERT(is_delaunay(*mesh,X,e)); // Update the BSP tree for the triangle flip const auto f0 = mesh->face(e), f1 = mesh->face(mesh->reverse(e)); const int node = bsp.append(Node(mesh->vertices(e),~f1.id,~f0.id)); set_links(bsp,face_to_bsp[f0],node); set_links(bsp,face_to_bsp[f1],node); face_to_bsp[f0] = vec(2*node+1,-1); face_to_bsp[f1] = vec(2*node+0,-1); if (self_check) { mesh->assert_consistent(); check_bsp(*mesh,bsp,face_to_bsp,X); } // Recurse to successor edges to e const auto e0 = mesh->next(e), e1 = mesh->prev(mesh->reverse(e)); stack.extend(vec(tuple(e0,mesh->vertices(e0)), tuple(e1,mesh->vertices(e1)))); if (self_check) assert_delaunay("self check 2: ",mesh,X,Tuple<>(),true); } } if (self_check) { mesh->assert_consistent(); assert_delaunay("self check 3: ",mesh,X); } } // Remove sentinels for (int i=0;i<3;i++) mesh->erase_last_vertex_with_reordering(); // If desired, check that the final mesh is Delaunay if (validate) assert_delaunay("delaunay validate: ",mesh,X); // Return the mesh with the sentinels removed return mesh; }
int RunGLTest (void) { #ifdef GL int mm=1; #else int mm = 0; #endif int mode=0; cam.x=0; cam.y=0; int bpp; int w = 200; int h = 200; int done = 0; int shrink=0; int grow=0; int gofullscreen=0; int mustresize = 1; int justresized = 0; xy ss = parsemodes(w,h,"mode",1,0,0); printf("wtf\n"); if (ss.x!=-1){w=ss.x;h=ss.y;}; SDL_Surface* s; #ifdef GL s=initsdl(w,h,&bpp,SDL_OPENGL #else gltextsdlsurface=s=initsdl(w,h,&bpp, #endif +0);printf("inito\n"); SDL_InitSubSystem( SDL_INIT_TIMER); SDL_EnableUNICODE(1); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY/2, SDL_DEFAULT_REPEAT_INTERVAL*2); #ifdef GL newtermmsg=GetFileIntoCharPointer1("newtermmsg"); printf("pretty far\n"); wm(w,h); int down=0; glEnable(GL_BLEND); glShadeModel(GL_FLAT); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glClearColor( 0.0, 0.0, 0.04, 0.0 ); glLineWidth(lv); #else gltextsdlsurface=s; #endif roteface *face1; roteface *activeface; face1=add_face(); activeface =face1 ; face1->next=add_face(); printf("still?\n"); add_terminal(face1); printf("2threaad\n"); loadl2(); struct state *nerv=0; #ifdef nerve nerv=nerverot_init(w,h); #endif int dirty=1; printf("mainloop descent commencing\n"); while( !done ) { lockterms(face1); if(dirty||faces_dirty(face1)) { dirty=0; facesclean(face1); #ifdef GL glClear(GL_COLOR_BUFFER_BIT); #else SDL_FillRect ( s, NULL, 0 ); #endif #ifndef GL #else if(nerv) { shownerv(nerv); dirty=1; } glPushMatrix(); glScalef(sx,sy,0.004); glTranslatef(cam.x,cam.y,0); #endif Uint8 * k; int integer; k=SDL_GetKeyState(&integer); if(k[SDLK_RCTRL]) focusline(activeface); int nf; switch(mode) { case 0: showfaces(face1); break; #ifdef GL case 1: krychlus(face1); break; #endif } #ifdef GL glPopMatrix(); #endif #ifndef GL SDL_UpdateRect(s,0,0,0,0); #else SDL_GL_SwapBuffers( ); #endif facesclean(face1); } #ifdef GL GLenum gl_error; gl_error = glGetError( ); if( gl_error != GL_NO_ERROR ) { if(gl_error==GL_STACK_OVERFLOW) printf("QUACK QUACK QUACK, OVERFLOVING STACK\n"); else if(gl_error==GL_INVALID_OPERATION) printf("INVALID OPERATION, PATIENT EXPLODED\n"); else fprintf( stderr, "testgl: OpenGL error: %d\n", gl_error ); } #endif char* sdl_error; sdl_error = SDL_GetError( ); if( sdl_error[0] != '\0' ) { fprintf(stderr, "testgl: SDL error '%s'\n", sdl_error); SDL_ClearError(); } SDL_TimerID x=0; if(dirty) x= SDL_AddTimer(55, NewTimerCallback, 0); unlockterms(face1); // printf("---------unlocked wating\n"); SDL_Event event; if(SDL_WaitEvent( &event )) { lockterms(face1); // printf("---------locked goooin %i\n", event.type); if(x)SDL_RemoveTimer(x);x=0; do { int mod=event.key.keysym.mod; int key=event.key.keysym.sym; Uint8 *keystate = SDL_GetKeyState(NULL); switch( event.type ) { #ifdef GL case SDL_MOUSEMOTION: if((SDL_BUTTON(1)|SDL_BUTTON(2))&SDL_GetMouseState(0,0)) { activeface->x+=event.motion.xrel; activeface->y+=event.motion.yrel; } if((SDL_BUTTON(3)|SDL_BUTTON(2))&SDL_GetMouseState(0,0)) { cam.x-=event.motion.xrel; cam.y-=event.motion.yrel; } break; #endif case SDL_KEYUP: { if ( (key == SDLK_RCTRL) ) { dirty=1; } } break; case SDL_KEYDOWN: if(mod&KMOD_RSHIFT&&(key==SDLK_PAGEUP||key==SDLK_PAGEDOWN)) { if(key==SDLK_PAGEUP) tscroll+=9; if(key==SDLK_PAGEDOWN) tscroll-=9; if(tscroll<0)tscroll=0; // printf("scroll:%i,logl:%i, log&%i, t:%i ,b:%i\n", tscroll,activeface->t->logl, activeface->t->log,activeface->t->scrolltop,activeface->t->scrollbottom); } else if(key==SDLK_RCTRL||mod&KMOD_RCTRL) { dirty=1; switch (key) { case SDLK_TAB: cycle(face1, &activeface); break; case SDLK_F2: gofullscreen=1; break; case SDLK_F3: rastio+=0.05; mustresize=1; dirty=1; break; case SDLK_F4: rastio-=0.05; mustresize=1; dirty=1; break; case SDLK_F5: sx-=0.001; sy+=0.001; break; case SDLK_F6: sx+=0.001; sy-=0.001; break; case SDLK_F7: savemode(w,h); break; case SDLK_F8: loadl2(); break; case SDLK_p: saveScreenshot(); break; #ifdef GL case SDLK_F9: lv-=1; glLineWidth(lv); break; case SDLK_F10: lv+=1; glLineWidth(lv); break; #endif case SDLK_F11: shrink=1; break; case SDLK_F12: grow=1; break; case SDLK_PAGEUP: mode++; if(mode>mm)mode= mm; break; case SDLK_INSERT: mode--; if(mode<0)mode= 0; break; case SDLK_END: resizooo(activeface, 0,1,keystate); break; case SDLK_HOME: resizooo(activeface, 0,-1,keystate); break; case SDLK_DELETE: resizooo(activeface, -1,0,keystate); break; case SDLK_PAGEDOWN: resizooo(activeface, 1,0,keystate); break; #ifdef nerve case SDLK_F1: if(nerv) { nerverot_free(nerv); dirty=1; nerv=0; } else { nerv=nerverot_init(w,h); dirty=1; } break; #endif } } else { if(activeface->t==0) { printf("debug messages r fun\n"); add_terminal(activeface); activeface->next=add_face(); } if ( (key >= SDLK_F1) && (key <= SDLK_F15) ) { char *k; if(asprintf(&k ,"kf%i", key-SDLK_F1+1)!=-1) { rote_vt_terminfo(activeface->t, k); free(k); } } else if ( (key == SDLK_SPACE) ) keyp(activeface,32); else #define magic(x) rote_vt_terminfo(activeface->t, x ) if ( (key == SDLK_BACKSPACE) ) magic( "kbs"); else if ( (key == SDLK_ESCAPE) ) keyp(activeface,27); else if ( (key == SDLK_LEFT) ) magic("kcub1"); else if ( (key == SDLK_RIGHT) ) magic( "kcuf1"); else if ( (key == SDLK_UP) ) magic( "kcuu1"); else if ( (key == SDLK_DOWN) ) magic( "kcud1"); else if ( (key == SDLK_END) ) magic( "kend"); else if ( (key == SDLK_HOME) ) magic("khome"); else if ( (key == SDLK_DELETE) ) magic( "kdch1"); else if ( (key == SDLK_PAGEDOWN) ) magic( "knp"); else if ( (key == SDLK_INSERT) ) magic( "kich1"); else if ( (key == SDLK_PAGEUP) ) magic ( "kpp" ); else if ( (key == SDLK_RETURN) ) keyp(activeface,10); else if( event.key.keysym.unicode && ( (event.key.keysym.unicode & 0xFF80) == 0 ) ) keyp(activeface, event.key.keysym.unicode); } break; case SDL_QUIT: done = 1; break; #ifndef GL case SDL_MOUSEBUTTONDOWN: rote_vt_mousedown(activeface->t,event.button.x/13, event.button.y/26); break; case SDL_MOUSEBUTTONUP: rote_vt_mouseup (activeface->t,event.button.x/13, event.button.y/26); break; case SDL_MOUSEMOTION: rote_vt_mousemove(activeface->t,event.button.x/13, event.button.y/26); break; #endif case SDL_VIDEORESIZE: { w=event.resize.w;h=event.resize.h; // printf("videoresize %i %i\n", w,h); dirty=1; if (s=SDL_SetVideoMode( w,h, bpp, s->flags ) ) // printf("hmm\n"); wm(w,h); if(!justresized) mustresize=1; justresized=0; } break; case SDL_USEREVENT: if(event.user.code==1) RemoveTerm(&activeface,&face1, event.user.data1); break; } } while (SDL_PollEvent(&event)); if (shrink||grow) { resize(&w,&h,&bpp,&s->flags,&shrink,&grow); wm(w,h); } if (mustresize) { mustresize=0; justresized=1; // if(activeface->t->cols!=event.resize.w/13/rastio|| // activeface->t->rows!=event.resize.h/26/rastio) //rote_vt_resize(activeface->t,event.resize.h/26/rastio ,event.resize.w/13/rastio); } if(gofullscreen) if(s->flags & SDL_FULLSCREEN ) { s=SDL_SetVideoMode( w,h, bpp, (s->flags & ~SDL_FULLSCREEN )); } else s=SDL_SetVideoMode( w,h, bpp, (s->flags | SDL_FULLSCREEN )); gofullscreen=0; unlockterms(face1); } } SDL_Quit( ); return(0); }
/****************************************************************************** Write out a jot .sm file. ******************************************************************************/ void write_sm() { LMESHptr mesh = make_shared<LMESH>(); int i=0; //******** Build the mesh ******** err_adv(debug, "read ply file: %d vertices, %d faces\n", nverts, nfaces); err_adv(debug, "building mesh:"); // Add vertices to mesh err_adv(debug, " adding vertices..."); for (i = 0; i < nverts; i++) mesh->add_vertex(Wpt(vlist[i]->x, vlist[i]->y, vlist[i]->z)); err_adv(debug, " done\n"); // Add per-vertex colors if needed if (per_vertex_color) { err_adv(debug, " adding colors..."); for (i = 0; i < nverts; i++) mesh->bv(i)->set_color(COLOR(vlist[i]->r, vlist[i]->g, vlist[i]->b)); err_adv(debug, " done\n"); } // Add faces err_adv(debug, " adding faces..."); for (i = 0; i < nfaces; i++) add_face(mesh, flist[i]); err_adv(debug, " done\n"); //******** Filter the mesh ******** err_adv(debug, "filtering mesh..."); // Remove any isolated vertices for (i=mesh->nverts()-1; i>=0; i--) { if (mesh->bv(i)->degree() == 0) { mesh->remove_vertex(mesh->bv(i)); } } mesh->changed(); // Remove duplicate vertices while we're at it mesh->remove_duplicate_vertices(false); // don't keep the bastards // Check for consistent orientation of normals bool is_bad = false; for (i=0; i<mesh->nedges(); i++) if (!mesh->be(i)->consistent_orientation()) is_bad = true; if (is_bad) err_msg("Warning: inconsistently oriented triangles -- can't fix"); // Optional: recenter mesh if (Config::get_var_bool("JOT_RECENTER")) mesh->recenter(); // Optional: print stats if (Config::get_var_bool("JOT_PRINT_MESH")) mesh->print(); err_adv(debug, "done\n"); //******** Write mesh ******** err_adv(debug, "writing mesh..."); mesh->write_stream(cout); err_adv(debug, "done\n"); }
SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3) { int index[4] = {v0, v1, v2, v3}; return add_face(index, 4); }
SubdFace *SubdMesh::add_face(int v0, int v1, int v2) { int index[3] = {v0, v1, v2}; return add_face(index, 3); }
void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3) { int index[4] = {v0, v1, v2, v3}; add_face(index, 4); }
/* Add a face with the given vertices */ void add_face(int a, int b, int c) { if (faces.len == faces.capacity) { /* Double size when we run out... */ faces.capacity *= 2; faces.nodes = (face_t **)realloc(faces.nodes, sizeof(face_t *) * faces.capacity); } if (vertices.len < a || vertices.len < b || vertices.len < c) { /* Frick... */ fprintf(stderr, "ERROR: Haven't yet collected enough vertices for the face %d %d %d (have %d)!\n", a, b, c, vertices.len); exit(1); } /* Create a new triangle */ faces.nodes[faces.len] = malloc(sizeof(face_t)); faces.nodes[faces.len]->a = vertices.nodes[a-1]; faces.nodes[faces.len]->b = vertices.nodes[b-1]; faces.nodes[faces.len]->c = vertices.nodes[c-1]; /* Calculate some normals */ vertex_t u = {.x = faces.nodes[faces.len]->b->x - faces.nodes[faces.len]->a->x, .y = faces.nodes[faces.len]->b->y - faces.nodes[faces.len]->a->y, .z = faces.nodes[faces.len]->b->z - faces.nodes[faces.len]->a->z}; vertex_t v = {.x = faces.nodes[faces.len]->c->x - faces.nodes[faces.len]->a->x, .y = faces.nodes[faces.len]->c->y - faces.nodes[faces.len]->a->y, .z = faces.nodes[faces.len]->c->z - faces.nodes[faces.len]->a->z}; /* Set the face normals */ faces.nodes[faces.len]->normal.x = ((u.y * v.z) - (u.z * v.y)); faces.nodes[faces.len]->normal.y = -((u.z * v.x) - (u.x * v.z)); faces.nodes[faces.len]->normal.z = ((u.x * v.y) - (u.y * v.x)); faces.len++; } void finish_normals() { /* Loop through vertices and accumulate normals for them */ for (uint32_t i = 0; i < faces.len; ++i) { /* Vertex a */ faces.nodes[i]->a->normal.x += faces.nodes[i]->normal.x; faces.nodes[i]->a->normal.y += faces.nodes[i]->normal.y; faces.nodes[i]->a->normal.z += faces.nodes[i]->normal.z; /* Vertex b */ faces.nodes[i]->b->normal.x += faces.nodes[i]->normal.x; faces.nodes[i]->b->normal.y += faces.nodes[i]->normal.y; faces.nodes[i]->b->normal.z += faces.nodes[i]->normal.z; /* Vertex c */ faces.nodes[i]->c->normal.x += faces.nodes[i]->normal.x; faces.nodes[i]->c->normal.y += faces.nodes[i]->normal.y; faces.nodes[i]->c->normal.z += faces.nodes[i]->normal.z; } } /* Discard the rest of this line */ void toss(FILE * f) { while (fgetc(f) != '\n'); } /* Load a Wavefront Obj model */ void load_wavefront(char * filename) { /* Open the file */ FILE * obj = fopen(filename, "r"); int collected = 0; char d = ' '; /* Initialize the lists */ init_model(); while (!feof(obj)) { /* Scan in a line */ collected = fscanf(obj, "%c ", &d); if (collected == 0) continue; switch (d) { case 'v': { /* Vertex */ float x, y, z; collected = fscanf(obj, "%f %f %f\n", &x, &y, &z); if (collected < 3) fprintf(stderr, "ERROR: Only collected %d points!\n", collected); add_vertex(x, y, z); } break; case 'f': { /* Face */ int a, b, c; collected = fscanf(obj, "%d %d %d\n", &a, &b, &c); if (collected < 3) fprintf(stderr, "ERROR: Only collected %d vertices!\n", collected); add_face(a,b,c); } break; default: /* Something else that we don't care about */ toss(obj); break; } } /* Finalize the vertex normals */ finish_normals(); fclose(obj); } /* Vertex, fragment, program */ GLuint v, f, p; /* Read a file into a buffer and return a pointer to the buffer */ char * readFile(char * filename, int32_t * size) { FILE * tex; char * texture; tex = fopen(filename, "r"); fseek(tex, 0L, SEEK_END); *size = ftell(tex); texture = malloc(*size); fseek(tex, 0L, SEEK_SET); fread(texture, *size, 1, tex); fclose(tex); return texture; }
// Retriangulate a cavity formed when a constraint edge is inserted, following Shewchuck and Brown. // The cavity is defined by a counterclockwise list of vertices v[0] to v[m-1] as in Shewchuck and Brown, Figure 5. static void cavity_delaunay(MutableTriangleTopology& parent_mesh, RawField<const EV,VertexId> X, RawArray<const VertexId> cavity, Random& random) { // Since the algorithm generates meshes which may be inconsistent with the outer mesh, and the cavity // array may have duplicate vertices, we use a temporary mesh and then copy the triangles over when done. // In the temporary, vertices are indexed consecutively from 0 to m-1. const int m = cavity.size(); assert(m >= 3); const auto mesh = new_<MutableTriangleTopology>(); Field<Perturbed2,VertexId> Xc(m,uninit); for (const int i : range(m)) Xc.flat[i] = Perturbed2(cavity[i].id,X[cavity[i]]); mesh->add_vertices(m); const auto xs = Xc.flat[0], xe = Xc.flat[m-1]; // Set up data structures for prev, next, pi in the paper const Field<VertexId,VertexId> prev(m,uninit), next(m,uninit); for (int i=0;i<m-1;i++) { next.flat[i] = VertexId(i+1); prev.flat[i+1] = VertexId(i); } const Array<VertexId> pi_(m-2,uninit); for (int i=1;i<=m-2;i++) pi_[i-1] = VertexId(i); #define PI(i) pi_[(i)-1] // Randomly shuffle [1,m-2], subject to vertices closer to xs-xe than both their neighbors occurring later for (int i=m-2;i>=2;i--) { int j; for (;;) { j = random.uniform<int>(0,i)+1; const auto pj = PI(j); if (!( segment_directions_oriented(xe,xs,Xc[pj],Xc[prev[pj]]) && segment_directions_oriented(xe,xs,Xc[pj],Xc[next[pj]]))) break; } swap(PI(i),PI(j)); // Remove PI(i) from the list const auto pi = PI(i); next[prev[pi]] = next[pi]; prev[next[pi]] = prev[pi]; } // Add the first triangle mesh->add_face(vec(VertexId(0),PI(1),VertexId(m-1))); // Add remaining triangles, flipping to ensure Delaunay const Field<bool,VertexId> marked(m); Array<HalfedgeId> fan; bool used_chew = false; for (int i=2;i<m-1;i++) { const auto pi = PI(i); insert_cavity_vertex(mesh,Xc,marked,pi,next[pi],prev[pi]); if (marked[pi]) { used_chew = true; marked[pi] = false; // Retriangulate the fans of triangles that have all three vertices marked auto e = mesh->reverse(mesh->halfedge(pi)); auto v = mesh->src(e); bool mv = marked[v]; marked[v] = false; fan.clear(); do { const auto h = mesh->prev(e); e = mesh->reverse(mesh->next(e)); v = mesh->src(e); const bool mv2 = marked[v]; marked[v] = false; if (mv) { if (mv2) fan.append(h); if (!mv2 || mesh->is_boundary(e)) { chew_fan(mesh,Xc,pi,fan,random); fan.clear(); } } mv = mv2; } while (!mesh->is_boundary(e)); } } #undef PI // If we ran Chew's algorithm, validate the output. I haven't tested this // case enough to be confident of its correctness. if (used_chew) assert_delaunay("Failure in extreme special case. If this triggers, please email [email protected]: ", mesh,Xc,Tuple<>(),false,false); // Copy triangles from temporary mesh to real mesh for (const auto f : mesh->faces()) { const auto v = mesh->vertices(f); parent_mesh.add_face(vec(cavity[v.x.id],cavity[v.y.id],cavity[v.z.id])); } }
// Delaunay retriangulate a triangle fan static void chew_fan(MutableTriangleTopology& parent_mesh, RawField<const Perturbed2,VertexId> X, const VertexId u, RawArray<HalfedgeId> fan, Random& random) { chew_fan_count_ += 1; #ifndef NDEBUG for (const auto e : fan) assert(parent_mesh.opposite(e)==u); for (int i=0;i<fan.size()-1;i++) GEODE_ASSERT(parent_mesh.src(fan[i])==parent_mesh.dst(fan[i+1])); #endif const int n = fan.size(); if (n < 2) return; chew_fan_count_ += 1024*n; // Collect vertices const Field<VertexId,VertexId> vertices(n+2,uninit); vertices.flat[0] = u; vertices.flat[1] = parent_mesh.src(fan[n-1]); for (int i=0;i<n;i++) vertices.flat[i+2] = parent_mesh.dst(fan[n-1-i]); // Delete original vertices for (const auto e : fan) parent_mesh.erase(parent_mesh.face(e)); // Make the vertices into a doubly linked list const Field<VertexId,VertexId> prev(n+2,uninit), next(n+2,uninit); prev.flat[0].id = n+1; next.flat[n+1].id = 0; for (int i=0;i<n+1;i++) { prev.flat[i+1].id = i; next.flat[i].id = i+1; } // Randomly shuffle the vertices, then pulling elements off the linked list in reverse order of our final shuffle. const Array<VertexId> pi(n+2,uninit); for (int i=0;i<n+2;i++) pi[i].id = i; random.shuffle(pi); for (int i=n+1;i>=0;i--) { const auto j = pi[i]; prev[next[j]] = prev[j]; next[prev[j]] = next[j]; } // Make a new singleton mesh const auto mesh = new_<MutableTriangleTopology>(); mesh->add_vertices(n+2); small_sort(pi[0],pi[1],pi[2]); mesh->add_face(vec(pi[0],pi[1],pi[2])); // Insert remaining vertices Array<HalfedgeId> work; for (int i=3;i<n+2;i++) { const auto j = pi[i]; const auto f = mesh->add_face(vec(j,next[j],prev[j])); work.append(mesh->reverse(mesh->opposite(f,j))); while (work.size()) { auto e = work.pop(); if ( !mesh->is_boundary(e) && incircle(X[vertices[mesh->src(e)]], X[vertices[mesh->dst(e)]], X[vertices[mesh->opposite(e)]], X[vertices[mesh->opposite(mesh->reverse(e))]])) { work.append(mesh->reverse(mesh->next(e))); work.append(mesh->reverse(mesh->prev(e))); e = mesh->unsafe_flip_edge(e); } } } // Copy triangles back to parent for (const auto f : mesh->faces()) { const auto vs = mesh->vertices(f); parent_mesh.add_face(vec(vertices[vs.x],vertices[vs.y],vertices[vs.z])); } }