void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset) { /* create inner grid */ float du = 1.0f/(float)Mu; float dv = 1.0f/(float)Mv; for(int j = 1; j < Mv; j++) { for(int i = 1; i < Mu; i++) { float u = i*du; float v = j*dv; add_vert(sub, u, v); if(i < Mu-1 && j < Mv-1) { int i1 = offset + 4 + (i-1) + (j-1)*(Mu-1); int i2 = offset + 4 + i + (j-1)*(Mu-1); int i3 = offset + 4 + i + j*(Mu-1); int i4 = offset + 4 + (i-1) + j*(Mu-1); add_triangle(i1, i2, i3); add_triangle(i1, i3, i4); } } } }
void plane(float length, float width, Vertex *res_vertices, Index *res_indices, D3DCOLOR color) { Index vertex = 0; // current vertex DWORD index = 0; // current index _ASSERT(PLANE_STEPS_PER_HALF_SIDE != 0); const float x_step = length/(2*PLANE_STEPS_PER_HALF_SIDE); const float y_step = width/(2*PLANE_STEPS_PER_HALF_SIDE); const Index vertices_in_line = (2*PLANE_STEPS_PER_HALF_SIDE + 1); D3DXVECTOR3 normal(0, 0, 1); for( int i = -PLANE_STEPS_PER_HALF_SIDE; i <= PLANE_STEPS_PER_HALF_SIDE; ++i ) { for( int j = -PLANE_STEPS_PER_HALF_SIDE; j <= PLANE_STEPS_PER_HALF_SIDE; ++j ) { res_vertices[vertex] = Vertex( D3DXVECTOR3( x_step*i, y_step*j, 0), color, normal); if( i != -PLANE_STEPS_PER_HALF_SIDE && j != -PLANE_STEPS_PER_HALF_SIDE) { // if not first line and column add_triangle(vertex, vertex-1, vertex-1-vertices_in_line, res_indices, index); add_triangle(vertex, vertex-1-vertices_in_line, vertex-vertices_in_line, res_indices, index); } ++vertex; } } }
void MeshBuilder::add_quad(const Math::Vector3<float>& pt1, const Math::Vector3<float>& pt2, const Math::Vector3<float>& pt3, const Math::Vector3<float>& pt4) { add_triangle(pt1, pt2, pt3); add_triangle(pt3, pt4, pt1); }
static void get_object_from_file(char *path, t_object **o, t_object *parent) { t_face *f; t_vertice *v; t_vertice_n *vn; double pt[3][3]; double n[3]; f = NULL; v = NULL; vn = NULL; get_coord(path, &v, &vn, &f); my_rev_list(&v); my_rev_n(&vn); my_rev_f(&f); while (f) { if (copy_tab(pt[0], get_itm(v, vn, 1, f->pos[0])) && copy_tab(pt[1], get_itm(v, vn, 1, f->pos[1])) && copy_tab(pt[2], get_itm(v, vn, 1, f->pos[2])) && copy_tab(n, get_itm(v, vn, 0, f->n))) add_triangle(o, pt, n, parent); f = f->next; } }
v3dmc_object load_object(GLchar *filename){ FILE *file; GLint i,npoints,nlines,ntriangles,nquads; v3dmc_object obj = object(); v3dmc_point p; v3dmc_line l; v3dmc_triangle t; v3dmc_quad q; file = fopen(filename,"r"); if(file!=NULL){ fread(&npoints,sizeof(int),1,file); fread(&nlines,sizeof(int),1,file); fread(&ntriangles,sizeof(int),1,file); fread(&nquads,sizeof(int),1,file); for(i=0;i<npoints;i++){ read_point(file,&p); add_point(&obj,p); } for(i=0;i<nlines;i++){ fread(&l,sizeof(v3dmc_line),1,file); add_line(&obj,l); } for(i=0;i<ntriangles;i++){ fread(&t,sizeof(v3dmc_triangle),1,file); add_triangle(&obj,t); } for(i=0;i<nquads;i++){ fread(&q,sizeof(v3dmc_quad),1,file); add_quad(&obj,q); } fclose(file); } return obj; }
void LightCaster::compute_light_mesh(Mesh* result, Walls* walls, const Vector_& light) { long nwalls = walls->nwalls(); angle = restrict_angle(angle); WallPoint* wall_points = (WallPoint*)GIGGLE->renderer->alloc(sizeof(WallPoint) * nwalls * 2); Wall** open_set = (Wall**)GIGGLE->renderer->alloc(sizeof(Wall*) * nwalls); long nopen_set = 0; for(long ii = 0; ii < nwalls; ++ii) { Wall* wall = &walls->walls[ii]; float angle_start = atan2f(wall->start.y - light.y, wall->start.x - light.x); float angle_end = atan2f(wall->end.y - light.y, wall->end.x - light.x); float dangle = restrict_angle(angle_end - angle_start); long idx1 = 2*ii; long idx2 = idx1 + 1; wall_points[idx1].point = &wall->start; wall_points[idx1].wall = wall; wall_points[idx1].angle = angle_start; wall_points[idx1].begin = dangle > 0; wall_points[idx2].point = &wall->end; wall_points[idx2].wall = wall; wall_points[idx2].angle = angle_end; wall_points[idx2].begin = !wall_points[idx1].begin; } std::sort(wall_points, wall_points + (nwalls*2), WallPointCompare()); float beginAngle = 0; for(int kk = 0; kk < 2; ++kk) { for(long ii = 0; ii < nwalls * 2; ++ii) { WallPoint* wp = &wall_points[ii]; Wall* last_closest = (nopen_set == 0) ? NULL : open_set[0]; if(wp->begin) { add_wall(open_set, &nopen_set, wp->wall, &light); } else { remove_wall(open_set, &nopen_set, wp->wall); } Wall* next_closest = (nopen_set == 0) ? NULL : open_set[0]; if(last_closest != next_closest) { float nextAngle = wp->angle; if(last_closest) { if(kk == 1) { add_triangle(result, light, last_closest, beginAngle, nextAngle); } beginAngle = nextAngle; } } } } }
void tessellate(const Vertex *src_vertices, const Index *src_indices, DWORD src_index_offset, Vertex *res_vertices, Index res_vertices_offset, Index *res_indices) // Divides each side of triangle into given number of parts // Writes data into arrays given as `res_vertices' and `res_indices', // assuming that there are already `res_vertices_offset' vertices before `res_vertices' pointer. { _ASSERT(src_vertices != NULL); _ASSERT(src_indices != NULL); _ASSERT(res_vertices != NULL); _ASSERT(res_indices != NULL); // i1, i2 i3 are indices of source triangle vertices const Index i1 = src_indices[src_index_offset]; const Index i2 = src_indices[src_index_offset + 1]; const Index i3 = src_indices[src_index_offset + 2]; const D3DXVECTOR3 step_down = (src_vertices[i1].pos - src_vertices[i2].pos)/TESSELATE_DEGREE; const D3DXVECTOR3 step_right = (src_vertices[i3].pos - src_vertices[i1].pos)/TESSELATE_DEGREE; res_vertices[0] = src_vertices[i2]; Index vertex = 1; // current vertex DWORD index = 0; // current index D3DXVECTOR3 start_pos = res_vertices[0].pos; for( Index line = 1; line <= TESSELATE_DEGREE; ++line ) { for( Index column = 0; column < line + 1; ++column ) // line #1 contains 2 vertices { res_vertices[vertex] = Vertex( start_pos + static_cast<FLOAT>(line)*step_down + static_cast<FLOAT>(column)*step_right ); if( column != 0 ) // not first coumn { // add outer triangle add_triangle( vertex, vertex - 1, vertex - line - 1, res_indices, index, res_vertices_offset ); } if( ( column != 0 ) && ( column != line ) ) // not first and not last column { // add inner triangle add_triangle( vertex, vertex - line - 1, vertex - line, res_indices, index, res_vertices_offset ); } ++vertex; } } }
void MeshBuilder::add_triangles() { while (_queue.size() >= 3) { MeshNode* n1 = _queue.front(); _queue.pop_front(); MeshNode* n2 = _queue.front(); _queue.pop_front(); MeshNode* n3 = _queue.front(); _queue.pop_front(); add_triangle(n1, n2, n3); } }
void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner) { if(inner.size() == 0 || outer.size() == 0) return; // XXX avoid crashes for Mu or Mv == 1, missing polygons /* stitch together two arrays of verts with triangles. at each step, we compare using the next verts on both sides, to find the split direction with the smallest diagonal, and use that in order to keep the triangle shape reasonable. */ for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) { int v0, v1, v2; v0 = inner[i]; v1 = outer[j]; if(j+1 == outer.size()) { v2 = inner[++i]; } else if(i+1 == inner.size()) { v2 = outer[++j]; } else { /* length of diagonals */ float len1 = len(mesh_P[inner[i]] - mesh_P[outer[j+1]]); float len2 = len(mesh_P[outer[j]] - mesh_P[inner[i+1]]); /* use smallest diagonal */ if(len1 < len2) v2 = outer[++j]; else v2 = inner[++i]; } add_triangle(v0, v1, v2); } }
void Vectorizer::process_triangle(int iv0, int iv1, int iv2, int level, scalar* xval, scalar* yval, double* phx, double* phy, int* idx) { if (level < LIN_MAX_LEVEL) { int i; if (!(level & 1)) { // obtain solution values and physical element coordinates xsln->set_quad_order(1, xitem); ysln->set_quad_order(1, yitem); xval = xsln->get_values(xia, xib); yval = ysln->get_values(yia, yib); for (i = 0; i < lin_np_tri[1]; i++) { double m = getmag(i); if (finite(m) && fabs(m) > max) max = fabs(m); } if (curved) { RefMap* refmap = xsln->get_refmap(); phx = refmap->get_phys_x(1); phy = refmap->get_phys_y(1); } idx = tri_indices[0]; } // obtain linearized values and coordinates at the midpoints double midval[4][3]; for (i = 0; i < 4; i++) { midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5; midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5; midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5; }; // determine whether or not to split the element bool split; if (eps >= 1.0) { //if eps > 1, the user wants a fixed number of refinements (no adaptivity) split = (level < eps); } else { // calculate the approximate error of linearizing the normalized solution double err = fabs(getmag(idx[0]) - midmag(0)) + fabs(getmag(idx[1]) - midmag(1)) + fabs(getmag(idx[2]) - midmag(2)); split = !finite(err) || err > max*3*eps; // do the same for the curvature if (curved && !split) { double cerr = 0.0, cden = 0.0; // fixme for (i = 0; i < 3; i++) { cerr += fabs(phx[idx[i]] - midval[0][i]) + fabs(phy[idx[i]] - midval[1][i]); cden += fabs(phx[idx[i]]) + fabs(phy[idx[i]]); } split = (cerr > cden*2.5e-4); } // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints if (level == 0 && !split) { split = (fabs(getmag(8) - 0.5*(midmag(0) + midmag(1))) + fabs(getmag(9) - 0.5*(midmag(1) + midmag(2))) + fabs(getmag(4) - 0.5*(midmag(2) + midmag(0)))) > max*3*eps; } } // split the triangle if the error is too large, otherwise produce a linear triangle if (split) { if (curved) for (i = 0; i < 3; i++) { midval[0][i] = phx[idx[i]]; midval[1][i] = phy[idx[i]]; } // obtain mid-edge vertices int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getvalx(idx[0]), getvaly(idx[0])); int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getvalx(idx[1]), getvaly(idx[1])); int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getvalx(idx[2]), getvaly(idx[2])); // recur to sub-elements push_transform(0); process_triangle(iv0, mid0, mid2, level+1, xval, yval, phx, phy, tri_indices[1]); pop_transform(); push_transform(1); process_triangle(mid0, iv1, mid1, level+1, xval, yval, phx, phy, tri_indices[2]); pop_transform(); push_transform(2); process_triangle(mid2, mid1, iv2, level+1, xval, yval, phx, phy, tri_indices[3]); pop_transform(); push_transform(3); process_triangle(mid1, mid2, mid0, level+1, xval, yval, phx, phy, tri_indices[4]); pop_transform(); return; } } // no splitting: output a linear triangle add_triangle(iv0, iv1, iv2); }
void MeshBuilder::add_triangle(const Math::Vector3<float>& pt1, const Math::Vector3<float>& pt2, const Math::Vector3<float>& pt3) { add_triangle(add_vertex(pt1), add_vertex(pt2), add_vertex(pt3)); }
void MeshBuilder::add_quad(MeshNode* n1, MeshNode* n2, MeshNode* n3, MeshNode* n4) { add_triangle(n1, n2, n3); add_triangle(n3, n4, n1); }
void Linearizer::process_quad(MeshFunction<double>** fns, int iv0, int iv1, int iv2, int iv3, int level, double* val, double* phx, double* phy, int* idx, bool curved) { double midval[3][5]; // try not to split through the vertex with the largest value int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1; int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3; a = (verts[a][2] > verts[b][2]) ? a : b; int flip = (a == iv1 || a == iv3) ? 1 : 0; if(level < LinearizerBase::get_max_level(fns[0]->get_active_element(), fns[0]->get_fn_order(), fns[0]->get_mesh())) { int i; if(!(level & 1)) // this is an optimization: do the following only every other time { // obtain solution values fns[0]->set_quad_order(1, item); val = fns[0]->get_values(component, value_type); if(auto_max) for (i = 0; i < lin_np_quad[1]; i++) { double v = val[i]; if(finite(v) && fabs(v) > max) #pragma omp critical(max) if(finite(v) && fabs(v) > max) max = fabs(v); } // This is just to make some sense. if(fabs(max) < Hermes::HermesSqrtEpsilon) max = Hermes::HermesSqrtEpsilon; idx = quad_indices[0]; if(curved) { RefMap* refmap = fns[0]->get_refmap(); phx = refmap->get_phys_x(1); phy = refmap->get_phys_y(1); double* dx = nullptr; double* dy = nullptr; if(this->xdisp != nullptr) fns[1]->set_quad_order(1, H2D_FN_VAL); if(this->ydisp != nullptr) fns[this->xdisp == nullptr ? 1 : 2]->set_quad_order(1, H2D_FN_VAL); if(this->xdisp != nullptr) dx = fns[1]->get_fn_values(); if(this->ydisp != nullptr) dy = fns[this->xdisp == nullptr ? 1 : 2]->get_fn_values(); for (i = 0; i < lin_np_quad[1]; i++) { if(this->xdisp != nullptr) phx[i] += dmult*dx[i]; if(this->ydisp != nullptr) phy[i] += dmult*dy[i]; } } } // obtain linearized values and coordinates at the midpoints for (i = 0; i < 3; i++) { midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5; midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5; midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5; midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5; midval[i][4] = (midval[i][0] + midval[i][2]) * 0.5; }; // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5; // determine whether or not to split the element int split; if(eps >= 1.0) { // if eps > 1, the user wants a fixed number of refinements (no adaptivity) split = (level < eps) ? 3 : 0; } else { if(!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max) { // do not split if the whole quad is above the specified maximum value split = 0; } else { // calculate the approximate error of linearizing the normalized solution double herr = fabs(val[idx[1]] - midval[2][1]) + fabs(val[idx[3]] - midval[2][3]); double verr = fabs(val[idx[0]] - midval[2][0]) + fabs(val[idx[2]] - midval[2][2]); double err = fabs(val[idx[4]] - midval[2][4]) + herr + verr; split = (!finite(err) || err > max*4*eps) ? 3 : 0; // decide whether to split horizontally or vertically only if(level > 0 && split) { if(herr > 5*verr) split = 1; // h-split else if(verr > 5*herr) split = 2; // v-split } } // also decide whether to split because of the curvature if(split != 3 && curved) { double cm2 = sqr(fns[0]->get_active_element()->get_diameter()*this->get_curvature_epsilon()); if(sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 || sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1; if(sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 || sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2; } // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints if(level == 0 && !split) { split = ((fabs(val[13] - 0.5*(midval[2][0] + midval[2][1])) + fabs(val[17] - 0.5*(midval[2][1] + midval[2][2])) + fabs(val[20] - 0.5*(midval[2][2] + midval[2][3])) + fabs(val[9] - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0; } } // split the quad if the error is too large, otherwise produce two linear triangles if(split) { if(curved) for (i = 0; i < 5; i++) { midval[0][i] = phx[idx[i]]; midval[1][i] = phy[idx[i]]; } // obtain mid-edge and mid-element vertices int mid0, mid1, mid2, mid3, mid4; if(split != 1) mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], val[idx[0]]); if(split != 2) mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], val[idx[1]]); if(split != 1) mid2 = get_vertex(iv2, iv3, midval[0][2], midval[1][2], val[idx[2]]); if(split != 2) mid3 = get_vertex(iv3, iv0, midval[0][3], midval[1][3], val[idx[3]]); if(split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], val[idx[4]]); if(!this->exceptionMessageCaughtInParallelBlock.empty()) return; // recur to sub-elements if(split == 3) { this->push_transforms(fns, 0); process_quad(fns, iv0, mid0, mid4, mid3, level + 1, val, phx, phy, quad_indices[1], curved); this->pop_transforms(fns); this->push_transforms(fns, 1); process_quad(fns, mid0, iv1, mid1, mid4, level + 1, val, phx, phy, quad_indices[2], curved); this->pop_transforms(fns); this->push_transforms(fns, 2); process_quad(fns, mid4, mid1, iv2, mid2, level + 1, val, phx, phy, quad_indices[3], curved); this->pop_transforms(fns); this->push_transforms(fns, 3); process_quad(fns, mid3, mid4, mid2, iv3, level + 1, val, phx, phy, quad_indices[4], curved); this->pop_transforms(fns); } else if(split == 1) // h-split { this->push_transforms(fns, 4); process_quad(fns, iv0, iv1, mid1, mid3, level + 1, val, phx, phy, quad_indices[5], curved); this->pop_transforms(fns); this->push_transforms(fns, 5); process_quad(fns, mid3, mid1, iv2, iv3, level + 1, val, phx, phy, quad_indices[6], curved); this->pop_transforms(fns); } else // v-split { this->push_transforms(fns, 6); process_quad(fns, iv0, mid0, mid2, iv3, level + 1, val, phx, phy, quad_indices[7], curved); this->pop_transforms(fns); this->push_transforms(fns, 7); process_quad(fns, mid0, iv1, iv2, mid2, level + 1, val, phx, phy, quad_indices[8], curved); this->pop_transforms(fns); } return; } } // output two linear triangles, if(!flip) { add_triangle(iv3, iv0, iv1, fns[0]->get_active_element()->marker); add_triangle(iv1, iv2, iv3, fns[0]->get_active_element()->marker); } else { add_triangle(iv0, iv1, iv2, fns[0]->get_active_element()->marker); add_triangle(iv2, iv3, iv0, fns[0]->get_active_element()->marker); } }
DANI_INLINE uint EpsTrimesh::split_edge(const uint eid, const vec3d point, std::vector<double> &radius, std::vector<vec3d> ¢ers, std::vector<vec3d> &antipodeans) { #ifdef CINOLIB uint e0 = edge_vertex_id(eid, 0); uint e1 = edge_vertex_id(eid, 1); uint vid = add_vertex(point); std::vector<int> rem_tris = adj_edg2tri(eid); for (uint tt : rem_tris) { uint opp_vid = vertex_opposite_to(tt, e0, e1); uint off_opp_vid = triangle_vertex_global_to_local(tt, opp_vid); uint t0 = add_triangle(vid, opp_vid, triangle_vertex_id(tt, (off_opp_vid+1) %3)); uint t1 = add_triangle(vid, triangle_vertex_id(tt, (off_opp_vid+2) %3), opp_vid); radius.push_back(radius.at(tt)); radius.push_back(radius.at(tt)); centers.push_back(centers.at(tt)); centers.push_back(centers.at(tt)); antipodeans.push_back(antipodeans.at(tt)); antipodeans.push_back(antipodeans.at(tt)); } std::sort (rem_tris.begin(), rem_tris.end()); std::reverse (rem_tris.begin(), rem_tris.end()); for (uint tt : rem_tris) { tris.at(tt*3+0) = INT_MAX; tris.at(tt*3+1) = INT_MAX; tris.at(tt*3+2) = INT_MAX; remove_unreferenced_triangle(tt); std::swap(radius.at(radius.size()-1), radius.at(tt)); radius.pop_back(); std::swap(antipodeans.at(antipodeans.size()-1), antipodeans.at(tt)); antipodeans.pop_back(); std::swap(centers.at(centers.size()-1), centers.at(tt)); centers.pop_back(); } edges.at(eid*2+0) = INT_MAX; edges.at(eid*2+1) = INT_MAX; remove_unreferenced_edge(eid); update_adjacency(); return vid; #else std::cerr << "[ERROR] Cinolib required to run this operation." << std::endl; exit(1); #endif }
void SurfTrack::defrag_mesh( ) { std::vector<Vec2st> old_edges = m_mesh.m_edges; PostDefragInfo info; info.m_defragged_vertex_map.clear(); // // First clear deleted vertices from the data stuctures // // do a quick pass through to see if any vertices have been deleted bool any_deleted = false; for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( m_mesh.vertex_is_deleted(i) ) { any_deleted = true; break; } } if ( !any_deleted ) { for ( size_t i = 0; i < get_num_vertices(); ++i ) { info.m_defragged_vertex_map.push_back( Vec2st(i,i) ); } } else { // Note: We could rebuild the mesh from scratch, rather than adding/removing // triangles, however this function is not a major computational bottleneck. size_t j = 0; std::vector<Vec3st> new_tris = m_mesh.get_triangles(); for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( !m_mesh.vertex_is_deleted(i) ) { pm_positions[j] = pm_positions[i]; pm_newpositions[j] = pm_newpositions[i]; m_masses[j] = m_masses[i]; info.m_defragged_vertex_map.push_back( Vec2st(i,j) ); // Now rewire the triangles containting vertex i // copy this, since we'll be changing the original as we go std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i]; for ( size_t t = 0; t < inc_tris.size(); ++t ) { Vec3st triangle = m_mesh.get_triangle( inc_tris[t] ); assert( triangle[0] == i || triangle[1] == i || triangle[2] == i ); if ( triangle[0] == i ) { triangle[0] = j; } if ( triangle[1] == i ) { triangle[1] = j; } if ( triangle[2] == i ) { triangle[2] = j; } remove_triangle(inc_tris[t]); // mark the triangle deleted add_triangle(triangle); // add the updated triangle } ++j; } } pm_positions.resize(j); pm_newpositions.resize(j); m_masses.resize(j); } // // Now clear deleted triangles from the mesh // m_mesh.set_num_vertices( get_num_vertices() ); m_mesh.clear_deleted_triangles( &info.m_defragged_triangle_map ); // // Update data carried on the edges // info.m_defragged_edge_map.clear(); info.m_defragged_edge_map.resize( old_edges.size(), UNINITIALIZED_SIZE_T ); // First update the set of edges to point to new vertex indices for ( size_t i = 0; i < old_edges.size(); ++i ) { for ( int v = 0; v < 2; ++v ) { const size_t old_v = old_edges[i][v]; size_t new_v = old_v; for ( size_t j = 0; j < info.m_defragged_vertex_map.size(); ++j ) { if ( info.m_defragged_vertex_map[j][0] == old_v ) { new_v = info.m_defragged_vertex_map[j][1]; assert( !m_mesh.vertex_is_deleted(new_v) ); break; } } old_edges[i][v] = new_v; } } // Now use this modified set of edges to find where the edge data maps to for ( unsigned int i = 0; i < old_edges.size(); ++i ) { if ( old_edges[i][0] == old_edges[i][1] ) { continue; } size_t new_edge_index = m_mesh.get_edge_index( old_edges[i][0], old_edges[i][1] ); // This edge has disappeared from the mesh. This can occur when trimming non-manifold flaps. if ( new_edge_index == m_mesh.m_edges.size() ) { continue; } info.m_defragged_edge_map[i] = new_edge_index; assert( new_edge_index < m_mesh.m_edges.size() ); // If the internal storage of the edge flipped, flip it back to original if ( old_edges[i][0] != m_mesh.m_edges[new_edge_index][0] ) { assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][0] ); assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][1] ); swap( m_mesh.m_edges[new_edge_index][0], m_mesh.m_edges[new_edge_index][1] ); assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][0] ); assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][1] ); } } for ( size_t i = 0; i < m_observers.size(); ++i ) { m_observers[i]->operationOccurred(*this, info); } if ( m_collision_safety ) { rebuild_continuous_broad_phase(); } }
void LinearizerBase::regularize_triangle(int iv0, int iv1, int iv2, int mid0, int mid1, int mid2, int marker) { // count the number of hanging mid-edge vertices int n = 0; if(mid0 >= 0) n++; if(mid1 >= 0) n++; if(mid2 >= 0) n++; if(n == 3) { // three hanging vertices: split into four triangles regularize_triangle(iv0, mid0, mid2, peek_vertex(iv0, mid0), -1, peek_vertex(mid2, iv0), marker); regularize_triangle(mid0, iv1, mid1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), -1, marker); regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker); regularize_triangle(mid0, mid1, mid2, -1, -1, -1, marker); } else if(n == 2) { // two hanging vertices: split into three triangles if(mid0 < 0) { regularize_triangle(iv0, iv1, mid1, peek_vertex(iv0, iv1), peek_vertex(iv1, mid1), -1, marker); regularize_triangle(mid2, iv0, mid1, peek_vertex(mid2, iv0), -1, -1, marker); regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker); } else if(mid1 < 0) { regularize_triangle(iv1, iv2, mid2, peek_vertex(iv1, iv2), peek_vertex(iv2, mid2), -1, marker); regularize_triangle(mid0, iv1, mid2, peek_vertex(mid0, iv1), -1, -1, marker); regularize_triangle(mid0, mid2, iv0, -1, peek_vertex(mid2, iv0), peek_vertex(iv0, mid0), marker); } else { regularize_triangle(iv2, iv0, mid0, peek_vertex(iv2, iv0), peek_vertex(iv0, mid0), -1, marker); regularize_triangle(mid1, iv2, mid0, peek_vertex(mid1, iv2), -1, -1, marker); regularize_triangle(mid1, mid0, iv1, -1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), marker); } } else if(n == 1) { // one hanging vertex: split into two triangles if(mid0 >= 0) { regularize_triangle(iv0, mid0, iv2, peek_vertex(iv0, mid0), -1, peek_vertex(iv2, iv0), marker); regularize_triangle(mid0, iv1, iv2, peek_vertex(mid0, iv1), peek_vertex(iv1, iv2), -1, marker); } else if(mid1 >= 0) { regularize_triangle(iv1, mid1, iv0, peek_vertex(iv1, mid1), -1, peek_vertex(iv0, iv1), marker); regularize_triangle(mid1, iv2, iv0, peek_vertex(mid1, iv2), peek_vertex(iv2, iv0), -1, marker); } else { regularize_triangle(iv2, mid2, iv1, peek_vertex(iv2, mid2), -1, peek_vertex(iv1, iv2), marker); regularize_triangle(mid2, iv0, iv1, peek_vertex(mid2, iv0), peek_vertex(iv0, iv1), -1, marker); } } else { // no hanging vertices: produce a single triangle add_triangle(iv0, iv1, iv2, marker); } }
void Orderizer::process_solution(Space* space) { // sanity check if (space == NULL) error("Space is NULL in Orderizer:process_solution()."); if (!space->is_up_to_date()) error("The space is not up to date."); int type = 1; nv = nt = ne = nl = 0; del_slot = -1; // estimate the required number of vertices and triangles Mesh* mesh = space->get_mesh(); if (mesh == NULL) { error("Mesh is NULL in Orderizer:process_solution()."); } int nn = mesh->get_num_active_elements(); int ev = 77 * nn, et = 64 * nn, ee = 16 * nn, el = nn + 10; // reuse or allocate vertex, triangle and edge arrays lin_init_array(verts, double3, cv, ev); lin_init_array(tris, int3, ct, et); lin_init_array(edges, int3, ce, ee); lin_init_array(lvert, int, cl1, el); lin_init_array(ltext, char*, cl2, el); lin_init_array(lbox, double2, cl3, el); info = NULL; int oo, o[6]; RefMap refmap; refmap.set_quad_2d(&quad_ord); // make a mesh illustrating the distribution of polynomial orders over the space Element* e; for_all_active_elements(e, mesh) { oo = o[4] = o[5] = space->get_element_order(e->id); for (unsigned int k = 0; k < e->nvert; k++) o[k] = space->get_edge_order(e, k); refmap.set_active_element(e); double* x = refmap.get_phys_x(type); double* y = refmap.get_phys_y(type); double3* pt = quad_ord.get_points(type); int np = quad_ord.get_num_points(type); int id[80]; assert(np <= 80); #define make_vert(index, x, y, val) \ { (index) = add_vertex(); \ verts[index][0] = (x); \ verts[index][1] = (y); \ verts[index][2] = (val); } int mode = e->get_mode(); if (e->is_quad()) { o[4] = H2D_GET_H_ORDER(oo); o[5] = H2D_GET_V_ORDER(oo); } make_vert(lvert[nl], x[0], y[0], o[4]); for (int i = 1; i < np; i++) make_vert(id[i-1], x[i], y[i], o[(int) pt[i][2]]); for (int i = 0; i < num_elem[mode][type]; i++) add_triangle(id[ord_elem[mode][type][i][0]], id[ord_elem[mode][type][i][1]], id[ord_elem[mode][type][i][2]]); for (int i = 0; i < num_edge[mode][type]; i++) { if (e->en[ord_edge[mode][type][i][2]]->bnd || (y[ord_edge[mode][type][i][0] + 1] < y[ord_edge[mode][type][i][1] + 1]) || ((y[ord_edge[mode][type][i][0] + 1] == y[ord_edge[mode][type][i][1] + 1]) && (x[ord_edge[mode][type][i][0] + 1] < x[ord_edge[mode][type][i][1] + 1]))) { add_edge(id[ord_edge[mode][type][i][0]], id[ord_edge[mode][type][i][1]], 0); } } double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100; for (unsigned int k = 0; k < e->nvert; k++) { if (e->vn[k]->x < xmin) xmin = e->vn[k]->x; if (e->vn[k]->x > xmax) xmax = e->vn[k]->x; if (e->vn[k]->y < ymin) ymin = e->vn[k]->y; if (e->vn[k]->y > ymax) ymax = e->vn[k]->y; } lbox[nl][0] = xmax - xmin; lbox[nl][1] = ymax - ymin; ltext[nl++] = labels[o[4]][o[5]]; }
void Vectorizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level, scalar* xval, scalar* yval, double* phx, double* phy, int* idx) { // try not to split through the vertex with the largest value int a = (magvert(iv0) > magvert(iv1)) ? iv0 : iv1; int b = (magvert(iv2) > magvert(iv3)) ? iv2 : iv3; a = (magvert(a) > magvert(b)) ? a : b; int flip = (a == iv1 || a == iv3) ? 1 : 0; if (level < LIN_MAX_LEVEL) { int i; if (!(level & 1)) { // obtain solution values and physical element coordinates xsln->set_quad_order(1, xitem); ysln->set_quad_order(1, yitem); xval = xsln->get_values(xia, xib); yval = ysln->get_values(yia, yib); for (i = 0; i < lin_np_quad[1]; i++) { double m = getmag(i); if (finite(m) && fabs(m) > max) max = fabs(m); } if (curved) { RefMap* refmap = xsln->get_refmap(); phx = refmap->get_phys_x(1); phy = refmap->get_phys_y(1); } idx = quad_indices[0]; } // obtain linearized values and coordinates at the midpoints double midval[4][5]; for (i = 0; i < 4; i++) { midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5; midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5; midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5; midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5; midval[i][4] = (midval[i][0] + midval[i][2]) * 0.5; }; // determine whether or not to split the element bool split; if (eps >= 1.0) { //if eps > 1, the user wants a fixed number of refinements (no adaptivity) split = (level < eps); } else { // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5; midval[3][4] = flip ? (verts[iv0][3] + verts[iv2][3]) * 0.5 : (verts[iv1][3] + verts[iv3][3]) * 0.5; // calculate the approximate error of linearizing the normalized solution double err = fabs(getmag(idx[0]) - midmag(0)) + fabs(getmag(idx[1]) - midmag(1)) + fabs(getmag(idx[2]) - midmag(2)) + fabs(getmag(idx[3]) - midmag(3)) + fabs(getmag(idx[4]) - midmag(4)); split = !finite(err) || err > max*4*eps; // do the same for the curvature if (curved && !split) { double cerr = 0.0, cden = 0.0; // fixme for (i = 0; i < 5; i++) { cerr += fabs(phx[idx[i]] - midval[0][i]) + fabs(phy[idx[i]] - midval[1][i]); cden += fabs(phx[idx[i]]) + fabs(phy[idx[i]]); } split = (cerr > cden*2.5e-4); } // do extra tests at level 0, so as not to miss functions with zero error at edge midpoints if (level == 0 && !split) { err = fabs(getmag(13) - 0.5*(midmag(0) + midmag(1))) + fabs(getmag(17) - 0.5*(midmag(1) + midmag(2))) + fabs(getmag(20) - 0.5*(midmag(2) + midmag(3))) + fabs(getmag(9) - 0.5*(midmag(3) + midmag(0))); split = !finite(err) || (err) > max*2*eps; //? } } // split the quad if the error is too large, otherwise produce two linear triangles if (split) { if (curved) for (i = 0; i < 5; i++) { midval[0][i] = phx[idx[i]]; midval[1][i] = phy[idx[i]]; } // obtain mid-edge and mid-element vertices int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getvalx(idx[0]), getvaly(idx[0])); int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getvalx(idx[1]), getvaly(idx[1])); int mid2 = get_vertex(iv2, iv3, midval[0][2], midval[1][2], getvalx(idx[2]), getvaly(idx[2])); int mid3 = get_vertex(iv3, iv0, midval[0][3], midval[1][3], getvalx(idx[3]), getvaly(idx[3])); int mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getvalx(idx[4]), getvaly(idx[4])); // recur to sub-elements push_transform(0); process_quad(iv0, mid0, mid4, mid3, level+1, xval, yval, phx, phy, quad_indices[1]); pop_transform(); push_transform(1); process_quad(mid0, iv1, mid1, mid4, level+1, xval, yval, phx, phy, quad_indices[2]); pop_transform(); push_transform(2); process_quad(mid4, mid1, iv2, mid2, level+1, xval, yval, phx, phy, quad_indices[3]); pop_transform(); push_transform(3); process_quad(mid3, mid4, mid2, iv3, level+1, xval, yval, phx, phy, quad_indices[4]); pop_transform(); return; } } // output two linear triangles, if (!flip) { add_triangle(iv3, iv0, iv1); add_triangle(iv1, iv2, iv3); } else { add_triangle(iv0, iv1, iv2); add_triangle(iv2, iv3, iv0); } }
/** * @brief EpsTrimesh::split_triangle * @param tid * @param point * @return */ DANI_INLINE uint EpsTrimesh::split_triangle(const uint tid, const vec3d point, std::vector<double> &radius, std::vector<vec3d> ¢ers, std::vector<vec3d> &antipodeans) { #ifdef CINOLIB uint nt = num_triangles(); uint vid = add_vertex(point); double r = radius.at(tid); vec3d a = antipodeans.at(tid); vec3d c = centers.at(tid); uint v0 = triangle_vertex_id(tid, 0); uint v1 = triangle_vertex_id(tid, 1); uint v2 = triangle_vertex_id(tid, 2); uint t0 = add_triangle(vid, v2, v0); uint t1 = add_triangle(vid, v0, v1); uint t2 = add_triangle(vid, v1, v2); radius.resize(num_triangles()); centers.resize(num_triangles()); antipodeans.resize(num_triangles()); radius.at(t0) = FLT_MAX; radius.at(t1) = FLT_MAX; radius.at(t2) = FLT_MAX; centers.at(t0) = {FLT_MAX}; centers.at(t1) = {FLT_MAX}; centers.at(t2) = {FLT_MAX}; antipodeans.at(t0) = {FLT_MAX}; antipodeans.at(t1) = {FLT_MAX}; antipodeans.at(t2) = {FLT_MAX}; tris.at(tid*3+0) = INT_MAX; tris.at(tid*3+1) = INT_MAX; tris.at(tid*3+2) = INT_MAX; if (tid == num_triangles()-1) { tris.resize(tris.size()-3); t_norm.resize(t_norm.size()-3); t_label.resize(t_label.size()-1); tri2edg.pop_back(); tri2tri.pop_back(); radius.pop_back(); antipodeans.pop_back(); centers.pop_back(); } else { remove_unreferenced_triangle(tid); std::swap(radius.at(radius.size()-1), radius.at(tid)); radius.pop_back(); std::swap(antipodeans.at(antipodeans.size()-1), antipodeans.at(tid)); antipodeans.pop_back(); std::swap(centers.at(centers.size()-1), centers.at(tid)); centers.pop_back(); } update_adjacency(); assert (num_triangles() == nt+2); assert (radius.size() == nt+2); assert (centers.size() == nt+2); assert (antipodeans.size() == nt+2); return vid; #else std::cerr << "[ERROR] Cinolib required to run this operation." << std::endl; exit(1); #endif }
void Linearizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level, scalar* val, double* phx, double* phy, int* idx) { double midval[3][5]; // try not to split through the vertex with the largest value int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1; int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3; a = (verts[a][2] > verts[b][2]) ? a : b; int flip = (a == iv1 || a == iv3) ? 1 : 0; if (level < LIN_MAX_LEVEL) { int i; if (!(level & 1)) // this is an optimization: do the following only every other time { // obtain solution values sln->set_quad_order(1, item); val = sln->get_values(ia, ib); if (auto_max) for (i = 0; i < lin_np_quad[1]; i++) { double v = getval(i); if (finite(v) && fabs(v) > max) max = fabs(v); } // obtain physical element coordinates if (curved || disp) { RefMap* refmap = sln->get_refmap(); phx = refmap->get_phys_x(1); phy = refmap->get_phys_y(1); if (disp) { xdisp->force_transform(sln); ydisp->force_transform(sln); xdisp->set_quad_order(1, FN_VAL); ydisp->set_quad_order(1, FN_VAL); scalar* dx = xdisp->get_fn_values(); scalar* dy = ydisp->get_fn_values(); for (i = 0; i < lin_np_quad[1]; i++) { phx[i] += dmult*realpart(dx[i]); phy[i] += dmult*realpart(dy[i]); } } } idx = quad_indices[0]; } // obtain linearized values and coordinates at the midpoints for (i = 0; i < 3; i++) { midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5; midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5; midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5; midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5; midval[i][4] = (midval[i][0] + midval[i][2]) * 0.5; }; // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5; // determine whether or not to split the element int split; if (eps >= 1.0) { // if eps > 1, the user wants a fixed number of refinements (no adaptivity) split = (level < eps) ? 3 : 0; } else { if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max) { // do not split if the whole quad is above the specified maximum value split = 0; } else { // calculate the approximate error of linearizing the normalized solution double herr = fabs(getval(idx[1]) - midval[2][1]) + fabs(getval(idx[3]) - midval[2][3]); double verr = fabs(getval(idx[0]) - midval[2][0]) + fabs(getval(idx[2]) - midval[2][2]); double err = fabs(getval(idx[4]) - midval[2][4]) + herr + verr; split = (!finite(err) || err > max*4*eps) ? 3 : 0; // decide whether to split horizontally or vertically only if (level > 0 && split) if (herr > 5*verr) split = 1; // h-split else if (verr > 5*herr) split = 2; // v-split } // also decide whether to split because of the curvature if (split != 3 && (curved || disp)) { double cm2 = sqr(cmax*5e-4); if (sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 || sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1; if (sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 || sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2; /*for (i = 0; i < 5; i++) if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1e-3)) { split = 1; break; }*/ } // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints if (level == 0 && !split) { split = ((fabs(getval(13) - 0.5*(midval[2][0] + midval[2][1])) + fabs(getval(17) - 0.5*(midval[2][1] + midval[2][2])) + fabs(getval(20) - 0.5*(midval[2][2] + midval[2][3])) + fabs(getval(9) - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0; } } // split the quad if the error is too large, otherwise produce two linear triangles if (split) { if (curved || disp) for (i = 0; i < 5; i++) { midval[0][i] = phx[idx[i]]; midval[1][i] = phy[idx[i]]; } // obtain mid-edge and mid-element vertices int mid0, mid1, mid2, mid3, mid4; if (split != 1) mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getval(idx[0])); if (split != 2) mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getval(idx[1])); if (split != 1) mid2 = get_vertex(iv2, iv3, midval[0][2], midval[1][2], getval(idx[2])); if (split != 2) mid3 = get_vertex(iv3, iv0, midval[0][3], midval[1][3], getval(idx[3])); if (split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getval(idx[4])); // recur to sub-elements if (split == 3) { sln->push_transform(0); process_quad(iv0, mid0, mid4, mid3, level+1, val, phx, phy, quad_indices[1]); sln->pop_transform(); sln->push_transform(1); process_quad(mid0, iv1, mid1, mid4, level+1, val, phx, phy, quad_indices[2]); sln->pop_transform(); sln->push_transform(2); process_quad(mid4, mid1, iv2, mid2, level+1, val, phx, phy, quad_indices[3]); sln->pop_transform(); sln->push_transform(3); process_quad(mid3, mid4, mid2, iv3, level+1, val, phx, phy, quad_indices[4]); sln->pop_transform(); } else if (split == 1) // h-split { sln->push_transform(4); process_quad(iv0, iv1, mid1, mid3, level+1, val, phx, phy, quad_indices[5]); sln->pop_transform(); sln->push_transform(5); process_quad(mid3, mid1, iv2, iv3, level+1, val, phx, phy, quad_indices[6]); sln->pop_transform(); } else // v-split { sln->push_transform(6); process_quad(iv0, mid0, mid2, iv3, level+1, val, phx, phy, quad_indices[7]); sln->pop_transform(); sln->push_transform(7); process_quad(mid0, iv1, iv2, mid2, level+1, val, phx, phy, quad_indices[8]); sln->pop_transform(); } return; } } // output two linear triangles, if (!flip) { add_triangle(iv3, iv0, iv1); add_triangle(iv1, iv2, iv3); } else { add_triangle(iv0, iv1, iv2); add_triangle(iv2, iv3, iv0); } }
void Linearizer::process_triangle(int iv0, int iv1, int iv2, int level, scalar* val, double* phx, double* phy, int* idx) { double midval[3][3]; if (level < LIN_MAX_LEVEL) { int i; if (!(level & 1)) { // obtain solution values sln->set_quad_order(1, item); val = sln->get_values(ia, ib); if (auto_max) for (i = 0; i < lin_np_tri[1]; i++) { double v = getval(i); if (finite(v) && fabs(v) > max) max = fabs(v); } // obtain physical element coordinates if (curved || disp) { RefMap* refmap = sln->get_refmap(); phx = refmap->get_phys_x(1); phy = refmap->get_phys_y(1); if (disp) { xdisp->force_transform(sln); ydisp->force_transform(sln); xdisp->set_quad_order(1, FN_VAL); ydisp->set_quad_order(1, FN_VAL); scalar* dx = xdisp->get_fn_values(); scalar* dy = ydisp->get_fn_values(); for (i = 0; i < lin_np_tri[1]; i++) { phx[i] += dmult*realpart(dx[i]); phy[i] += dmult*realpart(dy[i]); } } } idx = tri_indices[0]; } // obtain linearized values and coordinates at the midpoints for (i = 0; i < 3; i++) { midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5; midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5; midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5; }; // determine whether or not to split the element bool split; if (eps >= 1.0) { // if eps > 1, the user wants a fixed number of refinements (no adaptivity) split = (level < eps); } else { if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max) { // do not split if the whole triangle is above the specified maximum value split = false; } else { // calculate the approximate error of linearizing the normalized solution double err = fabs(getval(idx[0]) - midval[2][0]) + fabs(getval(idx[1]) - midval[2][1]) + fabs(getval(idx[2]) - midval[2][2]); split = !finite(err) || err > max*3*eps; } // do the same for the curvature if (!split && (curved || disp)) { for (i = 0; i < 3; i++) if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1.5e-3)) { split = true; break; } } // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints if (level == 0 && !split) { split = (fabs(getval(8) - 0.5*(midval[2][0] + midval[2][1])) + fabs(getval(9) - 0.5*(midval[2][1] + midval[2][2])) + fabs(getval(4) - 0.5*(midval[2][2] + midval[2][0]))) > max*3*eps; } } // split the triangle if the error is too large, otherwise produce a linear triangle if (split) { if (curved || disp) for (i = 0; i < 3; i++) { midval[0][i] = phx[idx[i]]; midval[1][i] = phy[idx[i]]; } // obtain mid-edge vertices int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getval(idx[0])); int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getval(idx[1])); int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getval(idx[2])); // recur to sub-elements sln->push_transform(0); process_triangle(iv0, mid0, mid2, level+1, val, phx, phy, tri_indices[1]); sln->pop_transform(); sln->push_transform(1); process_triangle(mid0, iv1, mid1, level+1, val, phx, phy, tri_indices[2]); sln->pop_transform(); sln->push_transform(2); process_triangle(mid2, mid1, iv2, level+1, val, phx, phy, tri_indices[3]); sln->pop_transform(); sln->push_transform(3); process_triangle(mid1, mid2, mid0, level+1, val, phx, phy, tri_indices[4]); sln->pop_transform(); return; } } // no splitting: output a linear triangle add_triangle(iv0, iv1, iv2); }
void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) { // XXX normals are flipped, why? /* grid is constructed starting from the outside edges, and adding progressively smaller inner triangles that connected to the outer one, until M = 1 or 2, the we fill up the last part. */ vector<int> outer_u, outer_v, outer_w; int m; /* add outer corners vertices */ { float2 p_u = make_float2(1.0f, 0.0f); float2 p_v = make_float2(0.0f, 1.0f); float2 p_w = make_float2(0.0f, 0.0f); int corner_u = add_vert(sub, p_u); int corner_v = add_vert(sub, p_v); int corner_w = add_vert(sub, p_w); outer_u.push_back(corner_v); outer_v.push_back(corner_w); outer_w.push_back(corner_u); for(int i = 1; i < ef.tu; i++) outer_u.push_back(add_vert(sub, interp(p_v, p_w, i/(float)ef.tu))); for(int i = 1; i < ef.tv; i++) outer_v.push_back(add_vert(sub, interp(p_w, p_u, i/(float)ef.tv))); for(int i = 1; i < ef.tw; i++) outer_w.push_back(add_vert(sub, interp(p_u, p_v, i/(float)ef.tw))); outer_u.push_back(corner_w); outer_v.push_back(corner_u); outer_w.push_back(corner_v); } for(m = M-2; m > 0; m -= 2) { vector<int> inner_u, inner_v, inner_w; float t = m/(float)M; float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f); /* 3 corner vertices */ float2 p_u = interp(center, make_float2(1.0f, 0.0f), t); float2 p_v = interp(center, make_float2(0.0f, 1.0f), t); float2 p_w = interp(center, make_float2(0.0f, 0.0f), t); int corner_u = add_vert(sub, p_u); int corner_v = add_vert(sub, p_v); int corner_w = add_vert(sub, p_w); /* construct array of vertex indices for each side */ inner_u.push_back(corner_v); inner_v.push_back(corner_w); inner_w.push_back(corner_u); for(int i = 1; i < m; i++) { /* add vertices between corners */ float t = i/(float)m; inner_u.push_back(add_vert(sub, interp(p_v, p_w, t))); inner_v.push_back(add_vert(sub, interp(p_w, p_u, t))); inner_w.push_back(add_vert(sub, interp(p_u, p_v, t))); } inner_u.push_back(corner_w); inner_v.push_back(corner_u); inner_w.push_back(corner_v); /* stitch together inner/outer with triangles */ stitch_triangles(outer_u, inner_u); stitch_triangles(outer_v, inner_v); stitch_triangles(outer_w, inner_w); outer_u = inner_u; outer_v = inner_v; outer_w = inner_w; } /* fill up last part */ if(m == -1) { /* single triangle */ add_triangle(outer_w[0], outer_u[0], outer_v[0]); } else { /* center vertex + 6 triangles */ int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f)); add_triangle(outer_w[0], outer_w[1], center); add_triangle(outer_w[1], outer_w[2], center); add_triangle(outer_u[0], outer_u[1], center); add_triangle(outer_u[1], outer_u[2], center); add_triangle(outer_v[0], outer_v[1], center); add_triangle(outer_v[1], outer_v[2], center); } }
struct obj_info * Part_import( int id_start ) { char line[MAX_LINE_SIZE]; struct obj_info *part; struct wmember reg_head; unsigned char rgb[3]; int surf_count=0; int id_end; int last_surf=0; int i; int tri[3]; int corner_index=-1; clean_vert_tree( tree_root ); VSETALL( rgb, 128 ); BU_ALLOC(part, struct obj_info); part->obj_type = PART_TYPE; part->obj_id = id_start; while ( bu_fgets( line, MAX_LINE_SIZE, fd_in ) ) { if ( !bu_strncmp( line, "PartName", 8 ) ) { line[strlen( line ) - 1] = '\0'; part->obj_name = bu_strdup( &line[9] ); lower_case( part->obj_name ); Make_brlcad_names( part ); } else if ( !bu_strncmp( line, "FaceCount", 9 ) ) { surf_count = atoi( &line[10] ); if ( surf_count == 0 ) { last_surf = 1; } } else if ( !bu_strncmp( line, "EndPartId", 9 ) ) { /* found end of part, check id */ id_end = atoi( &line[10] ); if ( id_end != id_start ) bu_exit( 1, "%s: ERROR: found end of part id %d while processing part %d\n", progname,id_end, id_start ); if ( last_surf ) { break; } } else if ( !bu_strncmp( line, "FaceRGB", 7 ) ) { /* get face color */ char *ptr; i = 8; ptr = strtok( &line[i], " \t" ); for ( i=0; i<3 && ptr; i++ ) { rgb[i] = atof( ptr ); ptr = strtok( (char *)NULL, " \t" ); } } else if ( !bu_strncmp( line, "Facet", 5 ) ) { /* read a triangle */ VSETALL( tri, -1 ); corner_index = -1; } else if ( !bu_strncmp( line, "Face", 4 ) ) { /* start of a surface */ int surf_no; surf_no = atoi( &line[5] ); if ( surf_no == surf_count ) { last_surf = 1; } } else if ( !bu_strncmp( line, "TriangleCount", 13 ) ) { /* get number of triangles for this surface */ } else if ( !bu_strncmp( line, "Vertices", 9 ) ) { /* get vertex list for this triangle */ } else if ( !bu_strncmp( line, "Vertex", 6 ) ) { /* get a vertex */ char *ptr = NULL; vect_t v = VINIT_ZERO; i = 7; while ( !isspace( (int)line[i] ) && line[i] != '\0' ) i++; ptr = strtok( &line[i], " \t" ); for ( i=0; i<3 && ptr; i++ ) { v[i] = atof( ptr ); ptr = strtok( (char *)NULL, " \t" ); } tri[++corner_index] = Add_vert( V3ARGS( v ), tree_root, local_tol_sq ); if ( corner_index == 2 ) { if ( !bad_triangle( tri, tree_root->the_array ) ) { add_triangle( tri ); } } } else if ( !bu_strncmp( line, "Normal", 6 ) ) { /* get a vertex normal */ } else if ( !bu_strncmp( line, "PointCount", 10 ) ) { /* get number of vertices for this surface */ } else bu_exit( 1, "%s: ERROR: unrecognized line encountered while processing part id %d:\n%s\n", progname,id_start, line ); } if ( curr_tri == 0 ) { /* no facets in this part, so ignore it */ bu_free( (char *)part, "part" ); part = (struct obj_info *)NULL; } else { /* write this part to database, first make a primitive solid */ if ( mk_bot( fd_out, part->brlcad_solid, RT_BOT_SOLID, RT_BOT_UNORIENTED, 0, tree_root->curr_vert, curr_tri, tree_root->the_array, part_tris, NULL, NULL ) ) bu_exit( 1, "%s: Failed to write primitive %s (%s) to database\n", progname,part->brlcad_solid, part->obj_name ); if ( verbose ) { DO_INDENT; bu_log( "Wrote BOT %s\n", part->brlcad_solid ); } /* then a region */ BU_LIST_INIT( ®_head.l ); if ( mk_addmember( part->brlcad_solid, ®_head.l, NULL, WMOP_UNION ) == WMEMBER_NULL ) bu_exit( 1, "%s: ERROR: Failed to add solid (%s), to region (%s)\n", progname,part->brlcad_solid, part->brlcad_comb ); if ( mk_comb( fd_out, part->brlcad_comb, ®_head.l, 1, NULL, NULL, rgb, ident++, 0, 1, 100, 0, 0, 0 ) ) bu_exit( 1, "%s: Failed to write region %s (%s) to database\n", progname,part->brlcad_comb, part->obj_name ); if ( verbose ) { DO_INDENT; bu_log( "Wrote region %s\n", part->brlcad_comb ); } if ( use_part_name_hash ) { if ( db5_update_attribute( part->brlcad_comb, "Part_No", part->obj_name, fd_out->dbip ) ) { bu_log( "Failed to assign Part_no attribute to %s\n", part->brlcad_comb ); } } } /* free some memory */ if ( part_tris ) { bu_free( (char *)part_tris, "part_tris" ); } max_tri = 0; curr_tri = 0; part_tris = NULL; return part; }
void SurfTrack::defrag_mesh( ) { // // First clear deleted vertices from the data stuctures // double start_time = get_time_in_seconds(); // do a quick pass through to see if any vertices have been deleted bool any_deleted = false; for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( m_mesh.vertex_is_deleted(i) ) { any_deleted = true; break; } } if ( !any_deleted ) { for ( size_t i = 0; i < get_num_vertices(); ++i ) { m_defragged_vertex_map.push_back( Vec2st(i,i) ); } double end_time = get_time_in_seconds(); g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time ); } else { // Note: We could rebuild the mesh from scratch, rather than adding/removing // triangles, however this function is not a major computational bottleneck. size_t j = 0; std::vector<Vec3st> new_tris = m_mesh.get_triangles(); for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( !m_mesh.vertex_is_deleted(i) ) { pm_positions[j] = pm_positions[i]; pm_newpositions[j] = pm_newpositions[i]; m_masses[j] = m_masses[i]; m_defragged_vertex_map.push_back( Vec2st(i,j) ); // Now rewire the triangles containting vertex i // copy this, since we'll be changing the original as we go std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i]; for ( size_t t = 0; t < inc_tris.size(); ++t ) { Vec3st triangle = m_mesh.get_triangle( inc_tris[t] ); assert( triangle[0] == i || triangle[1] == i || triangle[2] == i ); if ( triangle[0] == i ) { triangle[0] = j; } if ( triangle[1] == i ) { triangle[1] = j; } if ( triangle[2] == i ) { triangle[2] = j; } remove_triangle(inc_tris[t]); // mark the triangle deleted add_triangle(triangle); // add the updated triangle } ++j; } } pm_positions.resize(j); pm_newpositions.resize(j); m_masses.resize(j); } double end_time = get_time_in_seconds(); g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time ); // // Now clear deleted triangles from the mesh // m_mesh.set_num_vertices( get_num_vertices() ); m_mesh.clear_deleted_triangles( &m_defragged_triangle_map ); if ( m_collision_safety ) { rebuild_continuous_broad_phase(); } }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ cNodeKdtree* cKdtree::m_insert_rec(std::vector<cTriangle> &vet_tri, std::vector<VVector> &vet_vertex, std::vector<VVector> &vet_nor, int depth) { cNodeKdtree *node = NULL; if(vet_tri.empty()) { // ja eh uma folha return node; } if((int)vet_tri.size() == 1) { // vai ser a folha // insere no noh o indice do triangulo node = new cNodeKdtree(); add_triangle(vet_vertex[vet_tri[0].m_v[0]], vet_vertex[vet_tri[0].m_v[1]], vet_vertex[vet_tri[0].m_v[2]], m_data_tri, m_data_vet, m_data_nor); node->is_leaf = true; node->tri = (int) m_data_tri.size() - 1; return node; } std::vector<cTriangle> vet_tri_front; std::vector<VVector> vet_vertex_front, vet_nor_front; std::vector<cTriangle> vet_tri_back; std::vector<VVector> vet_vertex_back, vet_nor_back; // escolher o eixo e o valor do eixo int axis, axis_value; selected_plane_kdtree(vet_tri, vet_vertex, vet_nor, axis, axis_value, depth); printf("Axis: %d\tvalue: %d\n", axis, axis_value); VVector normal_plane, point; get_att(axis, axis_value, normal_plane, point); // cria o noh node = new cNodeKdtree(); node->is_leaf = false; node->axis = axis; node->axis_value = axis_value; vet_tri_front.clear(); vet_vertex_front.clear(); vet_nor_front.clear(); vet_tri_back.clear(); vet_vertex_back.clear(); vet_nor_back.clear(); // separar os triangulos for(int i = 0; i < (int)vet_tri.size(); i++) { int side = calculate_side(normal_plane, point, vet_vertex[vet_tri[i].m_v[0]], vet_vertex[vet_tri[i].m_v[1]], vet_vertex[vet_tri[i].m_v[2]]); if(side == CUT) { cut_triangle(normal_plane, point, i, vet_tri, vet_vertex, vet_nor, vet_tri_front, vet_vertex_front, vet_nor_front, vet_tri_back, vet_vertex_back, vet_nor_back); } else if(side == FRONT) { add_triangle(vet_vertex[vet_tri[i].m_v[0]], vet_vertex[vet_tri[i].m_v[1]], vet_vertex[vet_tri[i].m_v[2]], vet_tri_front, vet_vertex_front, vet_nor_front); } else// if(side == BACK) { add_triangle(vet_vertex[vet_tri[i].m_v[0]], vet_vertex[vet_tri[i].m_v[1]], vet_vertex[vet_tri[i].m_v[2]], vet_tri_back, vet_vertex_back, vet_nor_back); } } //vet_tri.clear(); vet_vertex.clear(); vet_nor.clear(); node->front = m_insert_rec(vet_tri_front, vet_vertex_front, vet_nor_front, depth + 1); node->back = m_insert_rec(vet_tri_back, vet_vertex_back, vet_nor_back, depth + 1); //vet_tri_front.clear(); vet_vertex_front.clear(); vet_nor_front.clear(); //vet_tri_back.clear(); vet_vertex_back.clear(); vet_nor_back.clear(); return node; }
struct model *load_obj_model(char *filename) { char dirname[1024]; char line[200]; struct model *model; struct mesh *curmesh = NULL; int fvp[20], fvt[20], fvn[20]; char *p, *s; int i, n; FILE *fp; strlcpy(dirname, filename, sizeof dirname); p = strrchr(dirname, '/'); if (!p) p = strrchr(dirname, '\\'); if (p) *p = 0; else strlcpy(dirname, ".", sizeof dirname); printf("loading obj model: %s\n", filename); fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "error: cannot load model '%s'\n", filename); return NULL; } model = malloc(sizeof(struct model)); memset(model, 0, sizeof(struct model)); model->min[0] = model->min[1] = model->min[2] = 1e10; model->max[0] = model->max[1] = model->max[2] = -1e10; model->radius = 0; while (1) { if (!fgets(line, sizeof line, fp)) break; s = strtok(line, SEP); if (!s) { continue; } else if (!strcmp(s, "v")) { char *x = strtok(NULL, SEP); char *y = strtok(NULL, SEP); char *z = strtok(NULL, SEP); add_position(model, atof(x), atof(y), atof(z)); } else if (!strcmp(s, "vt")) { char *u = strtok(NULL, SEP); char *v = strtok(NULL, SEP); add_texcoord(model, atof(u), atof(v)); } else if (!strcmp(s, "vn")) { char *x = strtok(NULL, SEP); char *y = strtok(NULL, SEP); char *z = strtok(NULL, SEP); add_normal(model, atof(x), atof(y), atof(z)); } else if (!strcmp(s, "f")) { n = 0; s = strtok(NULL, SEP); while (s) { if (*s) { splitfv(s, fvp+n, fvt+n, fvn+n); n++; } s = strtok(NULL, SEP); } for (i = 1; i < n - 1; i++) { add_triangle(curmesh, fvp[0], fvt[0], fvn[0], fvp[i], fvt[i], fvn[i], fvp[i+1], fvt[i+1], fvn[i+1]); } } else if (!strcmp(s, "mtllib")) { s = strtok(NULL, SEP); model->material = load_material(dirname, s); } else if (!strcmp(s, "usemtl")) { s = strtok(NULL, SEP); curmesh = find_mesh(model, s); } } model->radius = sqrtf(model->radius); fclose(fp); return model; }
struct model *load_obj_from_memory(const char *filename, unsigned char *data, int len) { char dirname[1024]; char *line, *next, *p, *s; struct model *model; struct mesh *mesh; int fvp[20], fvt[20], fvn[20]; int first, material; int i, n; printf("loading obj model '%s'\n", filename); strlcpy(dirname, filename, sizeof dirname); p = strrchr(dirname, '/'); if (!p) p = strrchr(dirname, '\\'); if (p) *p = 0; else strlcpy(dirname, "", sizeof dirname); mtl_count = 0; position.len = 0; texcoord.len = 0; normal.len = 0; element.len = 0; part.len = 0; first = 0; material = 0; data[len-1] = 0; /* over-write final newline to zero-terminate */ for (line = (char*)data; line; line = next) { next = strchr(line, '\n'); if (next) *next++ = 0; s = strtok(line, SEP); if (!s) { continue; } else if (!strcmp(s, "v")) { char *x = strtok(NULL, SEP); char *y = strtok(NULL, SEP); char *z = strtok(NULL, SEP); add_position(atof(x), atof(y), atof(z)); } else if (!strcmp(s, "vt")) { char *u = strtok(NULL, SEP); char *v = strtok(NULL, SEP); add_texcoord(atof(u), atof(v)); } else if (!strcmp(s, "vn")) { char *x = strtok(NULL, SEP); char *y = strtok(NULL, SEP); char *z = strtok(NULL, SEP); add_normal(atof(x), atof(y), atof(z)); } else if (!strcmp(s, "f")) { n = 0; s = strtok(NULL, SEP); while (s) { if (*s) { splitfv(s, fvp+n, fvn+n, fvt+n); n++; } s = strtok(NULL, SEP); } for (i = 1; i < n - 1; i++) { add_triangle(fvp[0], fvn[0], fvt[0], fvp[i], fvn[i], fvt[i], fvp[i+1], fvn[i+1], fvt[i+1]); } } else if (!strcmp(s, "mtllib")) { s = strtok(NULL, SEP); mtllib(dirname, s); } else if (!strcmp(s, "usemtl")) { if (element.len > first) push_part(&part, first, element.len, material); s = strtok(NULL, SEP); material = usemtl(s); first = element.len; } } if (element.len > first) push_part(&part, first, element.len, material); printf("\t%d parts; %d vertices; %d triangles", part.len, vertex.len/8, element.len/3); mesh = malloc(sizeof(struct mesh)); mesh->tag = TAG_MESH; mesh->enabled = 1<<ATT_POSITION | 1<<ATT_NORMAL | 1<<ATT_TEXCOORD; mesh->skel = NULL; mesh->inv_bind_matrix = NULL; mesh->count = part.len; mesh->part = malloc(part.len * sizeof(struct part)); memcpy(mesh->part, part.data, part.len * sizeof(struct part)); glGenVertexArrays(1, &mesh->vao); glGenBuffers(1, &mesh->vbo); glGenBuffers(1, &mesh->ibo); glBindVertexArray(mesh->vao); glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo); glBufferData(GL_ARRAY_BUFFER, vertex.len * 4, vertex.data, GL_STATIC_DRAW); glEnableVertexAttribArray(ATT_POSITION); glEnableVertexAttribArray(ATT_NORMAL); glEnableVertexAttribArray(ATT_TEXCOORD); glVertexAttribPointer(ATT_POSITION, 3, GL_FLOAT, 0, 32, (void*)0); glVertexAttribPointer(ATT_NORMAL, 3, GL_FLOAT, 0, 32, (void*)20); glVertexAttribPointer(ATT_TEXCOORD, 2, GL_FLOAT, 0, 32, (void*)12); glBufferData(GL_ELEMENT_ARRAY_BUFFER, element.len * 2, element.data, GL_STATIC_DRAW); model = malloc(sizeof *model); model->skel = NULL; model->mesh = mesh; model->anim = NULL; return model; }