/** * @brief Performs undo move. * * Takes back last move from move history and on the board. * * @return Nothing * @sa make_move() */ void undo_move(void) { int k; int i = get_last_move_i(); int j = get_last_move_j(); int color = get_last_move_color(); int count_stones = get_last_move_count_stones(); int stones[BOARD_SIZE_MAX * BOARD_SIZE_MAX][2]; if ( get_last_move_pass() ) { pop_move(); return; } get_last_move_stones(stones); set_vertex( EMPTY, i, j ); if ( count_stones > 0 ) { for ( k = 0; k < count_stones; k++ ) { set_vertex( color * -1, stones[k][0], stones[k][1] ); } if ( color == BLACK ) { set_black_captured( get_black_captured() - count_stones ); } else { set_white_captured( get_white_captured() - count_stones ); } } pop_move(); return; }
void Surface_mesh:: flip(Edge e) { // CAUTION : Flipping a halfedge may result in // a non-manifold mesh, hence check for yourself // whether this operation is allowed or not! //let's make it sure it is actually checked assert(is_flip_ok(e)); Halfedge a0 = halfedge(e, 0); Halfedge b0 = halfedge(e, 1); Halfedge a1 = next_halfedge(a0); Halfedge a2 = next_halfedge(a1); Halfedge b1 = next_halfedge(b0); Halfedge b2 = next_halfedge(b1); Vertex va0 = to_vertex(a0); Vertex va1 = to_vertex(a1); Vertex vb0 = to_vertex(b0); Vertex vb1 = to_vertex(b1); Face fa = face(a0); Face fb = face(b0); set_vertex(a0, va1); set_vertex(b0, vb1); set_next_halfedge(a0, a2); set_next_halfedge(a2, b1); set_next_halfedge(b1, a0); set_next_halfedge(b0, b2); set_next_halfedge(b2, a1); set_next_halfedge(a1, b0); set_face(a1, fb); set_face(b1, fa); set_halfedge(fa, a0); set_halfedge(fb, b0); if (halfedge(va0) == b0) set_halfedge(va0, a1); if (halfedge(vb0) == a0) set_halfedge(vb0, b1); }
/** * @brief Performs move * * Performs a move on the board and adds it to the move history. * * @param[in] color Color of stone to move * @param[in] i Horizontal coordinate of move * @param[in] j Vertical coordinate of move * @return Nothing * @sa undo_move() */ void make_move( int color, int i, int j ) { int nr_of_removed_stones; int group_nr; int nr_of_liberties; int group_size; int captured_now[BOARD_SIZE_MAX * BOARD_SIZE_MAX][2]; // Check for pass: if ( i == INVALID && j == INVALID ) { create_next_move(); set_move_pass(color); push_move(); return; } set_vertex( color, i, j ); scan_board_1(); nr_of_removed_stones = remove_stones( color * -1 ); if ( nr_of_removed_stones > 0 ) { scan_board_1(); } nr_of_removed_stones = get_captured_now(captured_now); create_next_move(); set_move_vertex( color, i, j ); set_move_captured_stones(captured_now); group_nr = get_worm_nr( i, j ); nr_of_liberties = get_nr_of_liberties(group_nr); group_size = get_size_of_worm(group_nr); // Check if this move is a ko: if ( nr_of_removed_stones == 1 && group_size == 1 && nr_of_liberties == 1 ) { // If only one stone has been captured it must be the first in the // captured_now list: set_move_ko( captured_now[0][0], captured_now[0][1] ); } push_move(); return; }
virtual void repaint() { if ( retry_count && !restore_objects() ) return; lpdev->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0L ); HRESULT rv = lpdev->BeginScene(); if( SUCCEEDED( rv ) ) { set_vertex( 0, 0, input_width, input_height, surface_width, surface_height, 0, 0, rcWindow.right, rcWindow.bottom ); lpdev->SetTexture( 0, lptex ); lpdev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); lpdev->EndScene(); if ( lpdev->Present( NULL, NULL, NULL, NULL ) == D3DERR_DEVICELOST ) retry_count = 60; } else retry_count = 60; ValidateRect( hWnd, & rcWindow ); }
/** * @brief Returnes list of valid moves for given color. * * This function takes a list of pseudo valid moves (as created by * get_pseudo_valid_move_list()) and drops the zero liberty moves. The * number of valid moves is returned. * * @param[in] color Color of moving side (BLACK|WHITE) * @param[out] valid_moves List of valid moves (zero liberty moves excluded) * @return Number of valid moves * @sa get_pseudo_valid_move_list() * @warning The function get_pseudo_valid_move_list() must be called * before get_valid_move_list(). */ int get_valid_move_list( int color, int valid_moves[][4] ) { int count; int i, j; int k, l; int nr_of_removed_stones; int captured_now[BOARD_SIZE_MAX * BOARD_SIZE_MAX][2]; int group_nr; int nr_of_liberties; bool is_valid; int temp_moves[BOARD_SIZE_MAX * BOARD_SIZE_MAX][4]; int value; int valid_moves_count; int atari_groups_player_before; int atari_groups_opponent_before; int atari_groups_player_after; int atari_groups_opponent_after; //int count_liberties_player_before; //int count_liberties_opponent_before; //int count_liberties_player_after; //int count_liberties_opponent_after; int value_list[COUNT_BRAINS]; //init_brains(); valid_moves_count = get_pseudo_valid_move_list( color, valid_moves ); for ( k = 0; k < BOARD_SIZE_MAX * BOARD_SIZE_MAX; k++ ) { temp_moves[k][0] = INVALID; // i coordinate temp_moves[k][1] = INVALID; // j coordinate temp_moves[k][2] = 0; // Value of move temp_moves[k][3] = 0; // Number of captured stones and atari ... } count = 0; for ( k = 0; k < valid_moves_count; k++ ) { is_valid = false; i = valid_moves[k][0]; j = valid_moves[k][1]; // Check for groups in atari before move is made: scan_board_1(); atari_groups_player_before = get_worm_count_atari(color); atari_groups_opponent_before = get_worm_count_atari( color * -1 ); //count_liberties_player_before = get_group_count_liberties(color); //count_liberties_opponent_before = get_group_count_liberties( color * -1 ); // Make move set_vertex( color, i, j ); scan_board_1(); nr_of_removed_stones = remove_stones( color * -1 ); // Check if this move is valid: if ( nr_of_removed_stones > 0 ) { is_valid = true; } else { group_nr = get_worm_nr( i, j ); nr_of_liberties = get_nr_of_liberties(group_nr); if ( nr_of_liberties > 0 ) { is_valid = true; } } atari_groups_player_after = get_worm_count_atari(color); atari_groups_opponent_after = get_worm_count_atari( color * -1 ); // Check if move gives atari: if ( atari_groups_opponent_after > atari_groups_opponent_before ) { temp_moves[k][3]++; } // Check if move avoids atari: if ( atari_groups_player_after < atari_groups_player_before ) { temp_moves[k][3]++; } //count_liberties_player_after = get_group_count_liberties(color); /* count_liberties_opponent_after = get_group_count_liberties( color * -1 ); if ( count_liberties_opponent_after < count_liberties_opponent_before) { temp_moves[k][3]++; } */ value = evaluate_position( value_list, false ); // Undo move: nr_of_removed_stones = get_captured_now(captured_now); set_vertex( EMPTY, i, j ); for ( l = 0; l < nr_of_removed_stones; l++ ) { set_vertex( color * -1, captured_now[l][0], captured_now[l][1] ); } if ( color == BLACK ) { set_black_captured( get_black_captured() - nr_of_removed_stones ); } else { set_white_captured( get_white_captured() - nr_of_removed_stones ); } // Save only valid moves in temporary list: if ( is_valid ) { temp_moves[count][0] = i; temp_moves[count][1] = j; temp_moves[count][2] = value; temp_moves[count][3] += nr_of_removed_stones; count++; } } // Copy only valid moves into valid_moves list: for ( k = 0; k < count; k++ ) { valid_moves[k][0] = temp_moves[k][0]; valid_moves[k][1] = temp_moves[k][1]; valid_moves[k][2] = temp_moves[k][2]; valid_moves[k][3] = temp_moves[k][3]; } valid_moves[count][0] = INVALID; valid_moves[count][1] = INVALID; // Sort valid moves list by value if ( color == BLACK ) { qsort( valid_moves, (size_t)count, sizeof(valid_moves[0]), compare_value_black ); } else { qsort( valid_moves, (size_t)count, sizeof(valid_moves[0]), compare_value_white ); } return count; }
void refresh() { if(lost && !recover()) return; RECT rd, rs; //dest, source rectangles GetClientRect(settings.handle, &rd); SetRect(&rs, 0, 0, settings.width, settings.height); //if output size changed, driver must be re-initialized. //failure to do so causes scaling issues on some video drivers. if(state.width != rd.right || state.height != rd.bottom) { init(); set_shader(shader_source_markup); return; } if(caps.shader && effect) { device->BeginScene(); set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom); D3DXVECTOR4 rubyTextureSize; rubyTextureSize.x = iwidth; rubyTextureSize.y = iheight; rubyTextureSize.z = 1.0 / iheight; rubyTextureSize.w = 1.0 / iwidth; effect->SetVector("rubyTextureSize", &rubyTextureSize); D3DXVECTOR4 rubyInputSize; rubyInputSize.x = settings.width; rubyInputSize.y = settings.height; rubyInputSize.z = 1.0 / settings.height; rubyInputSize.w = 1.0 / settings.width; effect->SetVector("rubyInputSize", &rubyInputSize); D3DXVECTOR4 rubyOutputSize; rubyOutputSize.x = rd.right; rubyOutputSize.y = rd.bottom; rubyOutputSize.z = 1.0 / rd.bottom; rubyOutputSize.w = 1.0 / rd.right; effect->SetVector("rubyOutputSize", &rubyOutputSize); UINT passes; effect->Begin(&passes, 0); effect->SetTexture("rubyTexture", texture); device->SetTexture(0, texture); for(unsigned pass = 0; pass < passes; pass++) { effect->BeginPass(pass); device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); effect->EndPass(); } effect->End(); device->EndScene(); } else { device->BeginScene(); set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom); device->SetTexture(0, texture); device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); device->EndScene(); } if(settings.synchronize) { D3DRASTER_STATUS status; //wait for a previous vblank to finish, if necessary while(true) { device->GetRasterStatus(0, &status); if(status.InVBlank == false) break; } //wait for next vblank to begin while(true) { device->GetRasterStatus(0, &status); if(status.InVBlank == true) break; } } if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true; }
void Surface_mesh:: split(Edge e, Vertex v) { Halfedge h0 = halfedge(e, 0); Halfedge o0 = halfedge(e, 1); Vertex v2 = to_vertex(o0); Halfedge e1 = new_edge(v, v2); Halfedge t1 = opposite_halfedge(e1); Face f0 = face(h0); Face f3 = face(o0); set_halfedge(v, h0); set_vertex(o0, v); if (!is_boundary(h0)) { Halfedge h1 = next_halfedge(h0); Halfedge h2 = next_halfedge(h1); Vertex v1 = to_vertex(h1); Halfedge e0 = new_edge(v, v1); Halfedge t0 = opposite_halfedge(e0); Face f1 = new_face(); set_halfedge(f0, h0); set_halfedge(f1, h2); set_face(h1, f0); set_face(t0, f0); set_face(h0, f0); set_face(h2, f1); set_face(t1, f1); set_face(e0, f1); set_next_halfedge(h0, h1); set_next_halfedge(h1, t0); set_next_halfedge(t0, h0); set_next_halfedge(e0, h2); set_next_halfedge(h2, t1); set_next_halfedge(t1, e0); } else { set_next_halfedge(prev_halfedge(h0), t1); set_next_halfedge(t1, h0); // halfedge handle of _vh already is h0 } if (!is_boundary(o0)) { Halfedge o1 = next_halfedge(o0); Halfedge o2 = next_halfedge(o1); Vertex v3 = to_vertex(o1); Halfedge e2 = new_edge(v, v3); Halfedge t2 = opposite_halfedge(e2); Face f2 = new_face(); set_halfedge(f2, o1); set_halfedge(f3, o0); set_face(o1, f2); set_face(t2, f2); set_face(e1, f2); set_face(o2, f3); set_face(o0, f3); set_face(e2, f3); set_next_halfedge(e1, o1); set_next_halfedge(o1, t2); set_next_halfedge(t2, e1); set_next_halfedge(o0, e2); set_next_halfedge(e2, o2); set_next_halfedge(o2, o0); } else { set_next_halfedge(e1, next_halfedge(o0)); set_next_halfedge(o0, e1); set_halfedge(v, e1); } if (halfedge(v2) == h0) set_halfedge(v2, t1); }
void Surface_mesh:: garbage_collection() { if (!garbage_) return; int i, i0, i1, nV(vertices_size()), nE(edges_size()), nH(halfedges_size()), nF(faces_size()); Vertex v; Halfedge h; Face f; if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false); if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false); if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false); // setup handle mapping Vertex_property<Vertex> vmap = add_vertex_property<Vertex>("v:garbage-collection"); Halfedge_property<Halfedge> hmap = add_halfedge_property<Halfedge>("h:garbage-collection"); Face_property<Face> fmap = add_face_property<Face>("f:garbage-collection"); for (i=0; i<nV; ++i) vmap[Vertex(i)] = Vertex(i); for (i=0; i<nH; ++i) hmap[Halfedge(i)] = Halfedge(i); for (i=0; i<nF; ++i) fmap[Face(i)] = Face(i); // remove deleted vertices if (nV > 0) { i0=0; i1=nV-1; while (1) { // find first deleted and last un-deleted while (!vdeleted_[Vertex(i0)] && i0 < i1) ++i0; while ( vdeleted_[Vertex(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap vprops_.swap(i0, i1); //add for(unsigned int j = 0;j<map_2skel.size();j++) { if(map_2skel[j] == i0) map_2skel[j] = i1; else if(map_2skel[j] == i1) map_2skel[j] = i0; } //end }; // remember new size nV = vdeleted_[Vertex(i0)] ? i0 : i0+1; } // remove deleted edges if (nE > 0) { i0=0; i1=nE-1; while (1) { // find first deleted and last un-deleted while (!edeleted_[Edge(i0)] && i0 < i1) ++i0; while ( edeleted_[Edge(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap eprops_.swap(i0, i1); hprops_.swap(2*i0, 2*i1); hprops_.swap(2*i0+1, 2*i1+1); }; // remember new size nE = edeleted_[Edge(i0)] ? i0 : i0+1; nH = 2*nE; } // remove deleted faces if (nF > 0) { i0=0; i1=nF-1; while (1) { // find 1st deleted and last un-deleted while (!fdeleted_[Face(i0)] && i0 < i1) ++i0; while ( fdeleted_[Face(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap fprops_.swap(i0, i1); }; // remember new size nF = fdeleted_[Face(i0)] ? i0 : i0+1; } // update vertex connectivity for (i=0; i<nV; ++i) { v = Vertex(i); if (!is_isolated(v)) set_halfedge(v, hmap[halfedge(v)]); } // update halfedge connectivity for (i=0; i<nH; ++i) { h = Halfedge(i); set_vertex(h, vmap[to_vertex(h)]); set_next_halfedge(h, hmap[next_halfedge(h)]); if (!is_boundary(h)) set_face(h, fmap[face(h)]); } // update handles of faces for (i=0; i<nF; ++i) { f = Face(i); set_halfedge(f, hmap[halfedge(f)]); } // remove handle maps remove_vertex_property(vmap); remove_halfedge_property(hmap); remove_face_property(fmap); // finally resize arrays vprops_.resize(nV); vprops_.free_memory(); hprops_.resize(nH); hprops_.free_memory(); eprops_.resize(nE); eprops_.free_memory(); fprops_.resize(nF); fprops_.free_memory(); deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0; garbage_ = false; }
void Surface_mesh:: remove_edge(Halfedge h) { Halfedge hn = next_halfedge(h); Halfedge hp = prev_halfedge(h); Halfedge o = opposite_halfedge(h); Halfedge on = next_halfedge(o); Halfedge op = prev_halfedge(o); Face fh = face(h); Face fo = face(o); Vertex vh = to_vertex(h); Vertex vo = to_vertex(o); // halfedge -> vertex Halfedge_around_vertex_circulator vh_it, vh_end; vh_it = vh_end = halfedges(vo); do { set_vertex(opposite_halfedge(vh_it), vh); } while (++vh_it != vh_end); // halfedge -> halfedge set_next_halfedge(hp, hn); set_next_halfedge(op, on); // face -> halfedge if (fh.is_valid()) set_halfedge(fh, hn); if (fo.is_valid()) set_halfedge(fo, on); // vertex -> halfedge if (halfedge(vh) == o) set_halfedge(vh, hn); adjust_outgoing_halfedge(vh); set_halfedge(vo, Halfedge()); // delete stuff if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false); if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false); vdeleted_[vo] = true; ++deleted_vertices_; edeleted_[edge(h)] = true; ++deleted_edges_; garbage_ = true; //add for(unsigned int j = 0;j < map_2skel.size();j++) { if(map_2skel[j] == vo.idx()) { //unsigned int tem = map_2skel[j]; map_2skel[j] = vh.idx(); //qDebug("vertex:[%d],change %d to %d",j,tem,vh.idx()); } } //end }
void create_clouds() { weather = (Weather*)malloc(sizeof(Weather)); //set a prevailaing wind direction. weather->x_prevailing_winds = 0.025f; weather->z_prevailing_winds = 0.035f; weather->initial_generation = MAXIMUM_CLOUDS; weather->cloud_count = 0; weather->clouds = (Cloud**)malloc(MAXIMUM_CLOUDS * sizeof(Cloud*)); GLfloat *data = malloc(sizeof(GLfloat) * 6 * 9 * 6); float n = 1.0f; int index = 0; // -z set_vertex(data,-n,n,-n,0,0,-1,1.0,1.0,1.0, &index); set_vertex(data, n,n,-n,0,0,-1,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,-n,0,0,-1,1.0,1.0,1.0, &index); set_vertex(data, n,n,-n,0,0,-1,1.0,1.0,1.0, &index); set_vertex(data,n,-n,-n,0,0,-1,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,-n,0,0,-1,1.0,1.0,1.0, &index); // +z set_vertex(data,-n,n,n,0,0,1,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,n,0,0,1,1.0,1.0,1.0, &index); set_vertex(data, n,n,n,0,0,1,1.0,1.0,1.0, &index); set_vertex(data, n,n,n,0,0,1,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,n,0,0,1,1.0,1.0,1.0, &index); set_vertex(data,n,-n,n,0,0,1,1.0,1.0,1.0, &index); // +x set_vertex(data,n,n, n,1,0,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n,-n,1,0,0,1.0,1.0,1.0, &index); set_vertex(data,n,n,-n,1,0,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n,-n,1,0,0,1.0,1.0,1.0, &index); set_vertex(data,n,n, n,1,0,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n,n,1,0,0,1.0,1.0,1.0, &index); // -x set_vertex(data,-n,n, n,-1,0,0,1.0,1.0,1.0, &index); set_vertex(data,-n,n,-n,-1,0,0,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,-n,-1,0,0,1.0,1.0,1.0, &index); set_vertex(data,-n,n, n,-1,0,0,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,-n,-1,0,0,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,n,-1,0,0,1.0,1.0,1.0, &index); // +y set_vertex(data,-n,n,n,0,1,0,1.0,1.0,1.0, &index); set_vertex(data,n,n, n,0,1,0,1.0,1.0,1.0, &index); set_vertex(data,-n,n,-n,0,1,0,1.0,1.0,1.0, &index); set_vertex(data,n,n, n,0,1,0,1.0,1.0,1.0, &index); set_vertex(data,n,n,-n,0,1,0,1.0,1.0,1.0, &index); set_vertex(data,-n,n,-n,0,1,0,1.0,1.0,1.0, &index); // -y set_vertex(data,-n,-n,-n,0,-1,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n, -n,0,-1,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n,n,0,-1,0,1.0,1.0,1.0, &index); set_vertex(data,n,-n, n,0,-1,0,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,n,0,-1,0,1.0,1.0,1.0, &index); set_vertex(data,-n,-n,-n,0,-1,0,1.0,1.0,1.0, &index); weather->cloud_vertex_buffer = gen_faces(9, 6, data); }
void Mesh::set_vertex(int index, Vector3 vector){ set_vertex(index, vector.x(), vector.y(), vector.z()); }
void operator ()(VcacheMesh &vcache_mesh, submesh_id_t const &submesh_id, ProgressCallback & progress_callback, bool const reorder_vertices = true) { //////// prerequisites ////////////////////// has_best_triangle = false; best_triangle = 0; optimized_tris.clear(); lru_cache.clear(); vtx_data.resize(get_num_vertices(vcache_mesh, submesh_id)); tri_data.resize(get_num_triangles(vcache_mesh, submesh_id)); // fetch the triangle data and put it in the internal vector // also fill the tri_indices_using vectors in the process { for (triangle_index_t tri_index = 0; tri_index < get_num_triangles(vcache_mesh, submesh_id); ++tri_index) { triangle_t triangle = get_triangle(vcache_mesh, submesh_id, tri_index); for (int i = 0; i < 3; ++i) { tri_data[tri_index].indices[i] = triangle[i]; vtx_data[triangle[i]].tri_indices_using.insert(tri_index); } } } //////// optimize triangles /////////////////////////// // calculate vertex and triangle scores { for (vertex_index_t vtx_index = 0; vtx_index < get_num_vertices(vcache_mesh, submesh_id); ++vtx_index) { vertex_data &vtx = vtx_data[vtx_index]; vtx.score = find_vertex_score(vtx); // calculate the vertex score for (typename tri_indices_using_t::const_iterator tri_idx_iter = vtx.tri_indices_using.begin(); tri_idx_iter != vtx.tri_indices_using.end(); ++tri_idx_iter) tri_data[*tri_idx_iter].score += vtx.score; // add the vertex score to the triangles using this vertex } } // tell the progress callback the maximum progress value set_maximum_optimizing_triangles_progress(progress_callback, tri_data.size()); /* the actual optimization step; reorder triangles by repeatedly finding a "best" triangle (= look at all the vertices in the LRU cache, and from all the triangles using these vertices, find the one with the highest score, remove this one from the vertices and put it in optimized_tris, and then find the next best triangle etc.) */ { size_t progress_counter = 0; while (optimized_tris.size() < tri_data.size()) { push_best_triangle(); ++progress_counter; set_current_optimizing_triangles_progress(progress_callback, progress_counter); } } //////// reoder vertices //////////////////////// if (reorder_vertices) { // even though *vertices* are reordered, reordering happens across *triangles* set_maximum_reordering_vertices_progress(progress_callback, tri_data.size()); // get the vertices from the mesh std::vector < vertex_t > src_vertices; src_vertices.resize(vtx_data.size()); for (vertex_index_t vtx_index = 0; vtx_index < vtx_data.size(); ++vtx_index) src_vertices[vtx_index] = get_vertex(vcache_mesh, submesh_id, vtx_index); // create and initialize the permutation sequence; // this sequence will be used for updating the triangle vertex indices later std::vector < std::pair < bool, vertex_index_t > > permutation; permutation.resize(vtx_data.size()); std::fill(permutation.begin(), permutation.end(), std::pair < bool, vertex_index_t > (false, 0)); /* reordering is done according to the order of access "access" refers to the triangles; for example, it makes no sense when the first triangle's vertices are at the end of the list of vertices, the second triangle's are in the middle etc. Instead, the first triangle's vertices should be at the beginning, the second triangle's should be right after these etc. */ size_t progress_counter = 0; vertex_index_t mesh_vertex_index = 0; for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index) { triangle_data const &tri = tri_data[tri_index]; // go through all 3 indices of each triangle, // and if it wasn't reordered, do so for (int i = 0; i < 3; ++i) { vertex_index_t vtx_index = tri.indices[i]; if (!permutation[vtx_index].first) // first false -> was not reordered yet { // check for overflow; it should never happen, since // each vertex is reordered only once assert(mesh_vertex_index < src_vertices.size()); // mark the vertex as reordered and store its new index permutation[vtx_index].first = true; permutation[vtx_index].second = mesh_vertex_index; // write the vertex at its new position in the mesh set_vertex(vcache_mesh, submesh_id, mesh_vertex_index, src_vertices[vtx_index]); ++mesh_vertex_index; } } ++progress_counter; set_current_reordering_vertices_progress(progress_callback, progress_counter); } // After the vertices have been reodered, the triangle vertex indices need to be updated for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index) { triangle_data &tri = optimized_tris[tri_index]; for (int i = 0; i < 3; ++i) tri.indices[i] = permutation[tri.indices[i]].second; } } // finally, store the contents of optimized_tris in the mesh { for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index) { triangle_data const &tri = optimized_tris[tri_index]; triangle_t new_triangle = create_new_triangle( vcache_mesh, tri.indices[0], tri.indices[1], tri.indices[2] ); set_triangle(vcache_mesh, submesh_id, tri_index, new_triangle); } } }