// Merge this with other, taking the outlines from other. // Other is not deleted, but left for the caller to handle. void BLOBNBOX::really_merge(BLOBNBOX* other) { if (cblob_ptr != NULL && other->cblob_ptr != NULL) { C_OUTLINE_IT ol_it(cblob_ptr->out_list()); ol_it.add_list_after(other->cblob_ptr->out_list()); } compute_bounding_box(); }
void ksearch_common(Point q, unsigned int k, long unsigned int query_point_index, qknn &que, float Eps) { Point bound_box_lower_corner, bound_box_upper_corner; Point low, high; que.set_size(k); eps=(float) 1.0+Eps; if (query_point_index >= (k)) query_point_index -= (k); else query_point_index=0; long unsigned int initial_scan_upper_range=query_point_index+2*k+1; if (initial_scan_upper_range > (long unsigned int)points.size()) initial_scan_upper_range = (long unsigned int)points.size(); low = points[query_point_index]; high = points[initial_scan_upper_range-1]; for (long unsigned int i=query_point_index; i<initial_scan_upper_range; ++i) { que.update(points[i].sqr_dist(q), pointers[i]); } compute_bounding_box(q, bound_box_lower_corner, bound_box_upper_corner, sqrt(que.topdist())); if (lt(bound_box_upper_corner, high) && lt(low,bound_box_lower_corner)) { return; } //Recurse through the entire set recurse(0, points.size(), q, que, bound_box_lower_corner, bound_box_upper_corner, query_point_index, initial_scan_upper_range); }
void Mesh::translateCenter(const Vec3& c) { for(int i = 0; i < numVtx(); ++i) { Vertex_handle v = find_vertex(i); v->point() -= c; } compute_bounding_box(); centerOfMass(); }
inline void recurse(long unsigned int s, // Starting index long unsigned int n, // Number of points Point q, // Query point qknn &ans, // Answer que Point &bound_box_lower_corner, Point &bound_box_upper_corner, long unsigned int initial_scan_lower_range, long unsigned int initial_scan_upper_range) { if (n < 4) { if (n == 0) return; bool update=false; for (long unsigned int i=0; i < n; ++i) { if ((s+i >= initial_scan_lower_range) && (s+i < initial_scan_upper_range)) continue; update = ans.update(points[s+i].sqr_dist(q), pointers[s+i]) || update; } if (update) compute_bounding_box(q, bound_box_lower_corner, bound_box_upper_corner, sqrt(ans.topdist())); return; } if ((s+n/2 >= initial_scan_lower_range) && (s+n/2 < initial_scan_upper_range)) { } else if (ans.update(points[s+n/2].sqr_dist(q), pointers[s+n/2])) compute_bounding_box(q, bound_box_lower_corner, bound_box_upper_corner, sqrt(ans.topdist())); double dsqb = lt.dist_sq_to_quad_box(q,points[s], points[s+n-1]); if (dsqb > ans.topdist()) return; if (lt(q,points[s+n/2])) { recurse(s, n/2, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range); if (lt(points[s+n/2],bound_box_upper_corner)) recurse(s+n/2+1,n-n/2-1, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range); } else { recurse(s+n/2+1, n-n/2-1, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range); if (lt(bound_box_lower_corner,points[s+n/2])) recurse(s, n/2, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range); } }
void Mesh::transformVertices(const TrMatrix& tr) { for(Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it) { Vec3& p = it->m_p; p = tr.multVec(Vec4(p)).toVec(); } // do some of the things done in finalize since all points were changed. compute_normals_per_facet(); compute_normals_per_vertex(); compute_bounding_box(); compute_triangle_surfaces(); centerOfMass(); }
/* Bounds handler for the pixbuf canvas item */ static void foo_canvas_pixbuf_bounds (FooCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { FooCanvasPixbuf *gcp; PixbufPrivate *priv; gcp = FOO_CANVAS_PIXBUF (item); priv = gcp->priv; if (!priv->pixbuf) { *x1 = *y1 = *x2 = *y2 = 0.0; return; } compute_bounding_box (gcp, 0.0, 0.0, x1, y1, x2, y2); }
/* Point handler for the pixbuf canvas item */ static double foo_canvas_pixbuf_point (FooCanvasItem *item, double x, double y, int cx, int cy, FooCanvasItem **actual_item) { FooCanvasPixbuf *gcp; PixbufPrivate *priv; double x1, y1, x2, y2; int px, py; double no_hit; guchar *src; GdkPixbuf *pixbuf; gcp = FOO_CANVAS_PIXBUF (item); priv = gcp->priv; pixbuf = priv->pixbuf; *actual_item = item; no_hit = item->canvas->pixels_per_unit * 2 + 10; if (!priv->pixbuf) return no_hit; compute_bounding_box (gcp, 0.0, 0.0, &x1, &y1, &x2, &y2); if (x < x1 || x >= x2 || y < y1 || y >= y2) return no_hit; if (!gdk_pixbuf_get_has_alpha (pixbuf) || priv->point_ignores_alpha) return 0.0; px = (x - x1) * gdk_pixbuf_get_width (pixbuf) / (x2 - x1); py = (y - y1) * gdk_pixbuf_get_height (pixbuf) / (y2 - y1); src = gdk_pixbuf_get_pixels (pixbuf) + py * gdk_pixbuf_get_rowstride (pixbuf) + px * gdk_pixbuf_get_n_channels (pixbuf); if (src[3] < 128) return no_hit; else return 0.0; }
void Mesh::rescaleAndCenter(float destdialen) { Vec3 dia = m_max - m_min; Vec3 center = (m_max + m_min) / 2.0; float dialen = qMax(dia.x, dia.y); float scale = destdialen/dialen; for(int i = 0; i < numVtx(); ++i) { Vertex_handle v = find_vertex(i); Vec3 &p = v->point(); p -= center; p *= scale; } compute_bounding_box(); centerOfMass(); }
void Mesh::finalize(bool needEdges) { buildVerticesInFaces(); if (!m_externalVtxNormals && !m_externalFaceNormals) { compute_normals_per_facet(); compute_normals_per_vertex(); } else if (!m_externalFaceNormals) { average_normals_per_facet(); } compute_bounding_box(); //mesh->estimateCurvature(); compute_triangle_surfaces(); centerOfMass(); //m_mesh->compute_volume(); if (needEdges) buildEdges(); }
// Rotates the box and the underlying blob. void BLOBNBOX::rotate(FCOORD rotation) { cblob_ptr->rotate(rotation); rotate_box(rotation); compute_bounding_box(); }
int main() { const uint n = 128; // 16384 const uint k = 4; // 128 const double std_dev = 0.75; //0.20 uint *idx = new uint[N]; data_type *data_points = new data_type[N]; uint *cntr_indices = new uint[K]; kdTree_type *heap = new kdTree_type[HEAP_SIZE]; data_type *initial_centre_positions= new data_type[K]; // read data points from file if (read_data_points(n,k,std_dev,data_points,idx) == false) return 1; // read intial centre from file (random placement if (read_initial_centres(n,k,std_dev,initial_centre_positions,cntr_indices) == false) return 1; // print initial centres printf("Initial centres\n"); for (uint i=0; i<k; i++) { printf("%d: ",i); for (uint d=0; d<D-1; d++) { printf("%d ",get_coord_type_vector_item(initial_centre_positions[i].value, d).to_int()); } printf("%d\n",get_coord_type_vector_item(initial_centre_positions[i].value, D-1).to_int()); } // compute axis-aligned hyper rectangle enclosing all data points data_type bnd_lo, bnd_hi; compute_bounding_box(data_points, idx, n, &bnd_lo, &bnd_hi); node_pointer root[P]; kdTree_type *tree_image = new kdTree_type[HEAP_SIZE]; node_pointer *tree_image_addr = new node_pointer[HEAP_SIZE]; uint z=0; uint ofs=0; recursive_split(1, n, bnd_lo, bnd_hi, idx, data_points,&z,&ofs,root,heap,tree_image,tree_image_addr,n,k,std_dev); data_type clusters_out[K]; coord_type_ext distortion_out[K]; // FIXME: get automatic co-simulation working /* for (uint i=0; i<P; i++) { root[i] = 0; } for (uint i=0; i<2*n-1; i++) { tree_image[i].bnd_hi = bnd_hi; tree_image[i].bnd_lo = bnd_lo; tree_image[i].count.VAL = i; tree_image[i].idx = NULL; tree_image[i].left.VAL = 0; tree_image[i].right.VAL = 0; tree_image[i].midPoint = bnd_hi; tree_image[i].sum_sq.VAL = 0; tree_image[i].wgtCent = conv_short_to_long(bnd_hi); tree_image_addr[i].VAL = i; } */ filtering_algorithm_top(tree_image,tree_image_addr,initial_centre_positions,2*n-1-1-(P-1),k-1,root,distortion_out,clusters_out); // print initial centres printf("New centres after clustering\n"); for (uint i=0; i<k; i++) { printf("%d: ",i); for (uint d=0; d<D-1; d++) { printf("%d ",get_coord_type_vector_item(clusters_out[i].value, d).to_int()); } printf("%d\n",get_coord_type_vector_item(clusters_out[i].value, D-1).to_int()); } delete idx; delete data_points; delete initial_centre_positions; delete cntr_indices; // FIXME: find out why C simulation reports memory fault if I don't comment these lines out //delete heap; //delete tree_image; //delete tree_image_addr; return 0; }
/* Update handler for the pixbuf canvas item */ static void foo_canvas_pixbuf_update (FooCanvasItem *item, double i2w_dx, double i2w_dy, int flags) { FooCanvasPixbuf *gcp; PixbufPrivate *priv; double bbox_x0, bbox_y0, bbox_x1, bbox_y1; int w, h; gcp = FOO_CANVAS_PIXBUF (item); priv = gcp->priv; if (parent_class->update) (* parent_class->update) (item, i2w_dx, i2w_dy, flags); /* If we need a pixbuf update, or if the item changed visibility to * shown, recompute the bounding box. */ if (priv->need_pixbuf_update || priv->need_xform_update || (flags & FOO_CANVAS_UPDATE_DEEP)) { foo_canvas_item_request_redraw (item); compute_bounding_box (gcp, i2w_dx, i2w_dy, &bbox_x0, &bbox_y0, &bbox_x1, &bbox_y1); foo_canvas_w2c_d (item->canvas, bbox_x0, bbox_y0, &item->x1, &item->y1); foo_canvas_w2c_d (item->canvas, bbox_x1, bbox_y1, &item->x2, &item->y2); item->x1 = floor (item->x1 + .5); item->y1 = floor (item->y1 + .5); item->x2 = floor (item->x2 + .5); item->y2 = floor (item->y2 + .5); #ifdef FOO_CANVAS_PIXBUF_VERBOSE g_print ("BBox is %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); #endif if (priv->pixbuf) { w = item->x2 - item->x1; h = item->y2 - item->y1; if (priv->pixbuf_scaled) g_object_unref (priv->pixbuf_scaled); if (gdk_pixbuf_get_width (priv->pixbuf) != w || gdk_pixbuf_get_height (priv->pixbuf) != h) priv->pixbuf_scaled = gdk_pixbuf_scale_simple ( priv->pixbuf, w, h, priv->interp_type); else priv->pixbuf_scaled = g_object_ref (priv->pixbuf); } foo_canvas_item_request_redraw (item); priv->need_pixbuf_update = FALSE; priv->need_xform_update = FALSE; } }
void sfcnn_knng_work<Point, Ptype>::sfcnn_knng_work_init(long int N, unsigned int k, int num_threads) { zorder_lt<Point> lt; Point bound_box_lower_corner, bound_box_upper_corner; double distance; long int range_b; long int range_e; if(N==0) { std::cerr << "Error: Input Point List has size 0"<< std::endl; exit(1); } max = (std::numeric_limits<Ptype>::max)(); min = (std::numeric_limits<Ptype>::min)(); answer.resize(N); int SR = 2*k; #ifdef _OPENMP long int chunk = N/num_threads; omp_set_num_threads(num_threads); #endif pair_iter<typename std::vector<Point>::iterator, typename std::vector<long unsigned int>::iterator> a(points.begin(), pointers.begin()), b(points.end(), pointers.end()); sort(a,b,lt); std::vector<qknn> que; que.resize(N); #ifdef _OPENMP #pragma omp parallel private(distance, range_b, range_e) #endif { #ifdef _OPENMP #pragma omp for schedule(static, chunk) #endif for(long int i=0;i < N;++i) { range_b = i-SR; if(range_b < 0) range_b = 0; range_e = i+SR+1; if(range_e > N) range_e = N; que[i].set_size(k); for(long int j=range_b;j < i;++j) { distance = points[i].sqr_dist(points[j]); que[i].update(distance, pointers[j]); } for(long int j=i+1;j < range_e;++j) { distance = points[i].sqr_dist(points[j]); que[i].update(distance, pointers[j]); } } } #ifdef _OPENMP #pragma omp parallel private(distance, range_b, range_e, bound_box_lower_corner, bound_box_upper_corner) #endif { #ifdef _OPENMP #pragma omp for schedule(static, chunk) #endif for(long int i=0;i < N;++i) { range_b = i-SR; if(range_b < 0) range_b = 0; range_e = i+SR+1; if(range_e > N) range_e = N; compute_bounding_box(points[i], bound_box_lower_corner, bound_box_upper_corner, sqrt(que[i].topdist())); if(!lt(bound_box_upper_corner, points[range_e-1]) || !lt(points[range_b], bound_box_lower_corner)) { recurse(0, N, i, que[i], bound_box_lower_corner, bound_box_upper_corner, (long unsigned int) range_b, (long unsigned int) range_e, lt); } que[i].answer(answer[pointers[i]]); } } points.clear(); pointers.clear(); }
void sfcnn_knng_work<Point, Ptype>::recurse(long unsigned int s, // Starting index long unsigned int n, // Number of points long int q, qknn &ans, // Answer que Point &bound_box_lower_corner, Point &bound_box_upper_corner, long unsigned int initial_scan_lower_range, long unsigned int initial_scan_upper_range, zorder_lt<Point> <) { double distance; if(n < 4) { if(n == 0) return; bool update=false; for(long unsigned int i=0;i < n;++i) { if((s+i >= initial_scan_lower_range) && (s+i < initial_scan_upper_range)) continue; distance = points[q].sqr_dist(points[s+i]); update = ans.update(distance, pointers[s+i]) || update; } if(update) compute_bounding_box(points[q], bound_box_lower_corner, bound_box_upper_corner, sqrt(ans.topdist())); return; } if((s+n/2 >= initial_scan_lower_range) && (s+n/2 < initial_scan_upper_range)) { } else { distance = points[q].sqr_dist(points[s+n/2]); if(ans.update(distance, pointers[s+n/2])) compute_bounding_box(points[q], bound_box_lower_corner, bound_box_upper_corner, sqrt(ans.topdist())); } if((lt.dist_sq_to_quad_box(points[q],points[s], points[s+n-1])) > ans.topdist()) return; if(lt(points[q],points[s+n/2])) { recurse(s, n/2, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range, lt); if(lt(points[s+n/2],bound_box_upper_corner)) recurse(s+n/2+1,n-n/2-1, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range, lt); } else { recurse(s+n/2+1, n-n/2-1, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range, lt); if(lt(bound_box_lower_corner,points[s+n/2])) recurse(s, n/2, q, ans, bound_box_lower_corner, bound_box_upper_corner, initial_scan_lower_range, initial_scan_upper_range, lt); } }
//determine bounding box from point cloud positions auto init_box(const ndarray<real_t, 2> position) const { return compute_bounding_box(position.view<vector_t>()); }
//In fact its function is same to compute_bounding_box? void Instance::set_bounding_box(void) { compute_bounding_box(); }
std::list<VoronoiShard> voronoi_convex_hull_shatter(const gl::MeshPtr &the_mesh, const std::vector<glm::vec3>& the_voronoi_points) { // points define voronoi cells in world space (avoid duplicates) // verts = source (convex hull) mesh vertices in local space std::list<VoronoiShard> ret; std::vector<glm::vec3> mesh_verts = the_mesh->geometry()->vertices(); auto convexHC = std::make_shared<btConvexHullComputer>(); btAlignedObjectArray<btVector3> vertices; btVector3 rbb, nrbb; btScalar nlength, maxDistance, distance; std::vector<glm::vec3> sortedVoronoiPoints = the_voronoi_points; btVector3 normal, plane; btAlignedObjectArray<btVector3> planes, convexPlanes; std::set<int> planeIndices; std::set<int>::iterator planeIndicesIter; int numplaneIndices; int i, j, k; // Normalize verts (numerical stability), convert to world space and get convexPlanes int numverts = mesh_verts.size(); // auto aabb = the_mesh->boundingBox(); // float scale_val = 1.f;//std::max(std::max(aabb.width(), aabb.height()), aabb.depth()); auto mesh_transform = the_mesh->global_transform() ;//* scale(glm::mat4(), vec3(1.f / scale_val)); std::vector<glm::vec3> world_space_verts; world_space_verts.resize(mesh_verts.size()); for (i = 0; i < numverts ;i++) { world_space_verts[i] = (mesh_transform * vec4(mesh_verts[i], 1.f)).xyz(); } //btGeometryUtil::getPlaneEquationsFromVertices(chverts, convexPlanes); // Using convexHullComputer faster than getPlaneEquationsFromVertices for large meshes... convexHC->compute(&world_space_verts[0].x, sizeof(world_space_verts[0]), numverts, 0.0, 0.0); int numFaces = convexHC->faces.size(); int v0, v1, v2; // vertices // get plane equations for the convex-hull n-gons for (i = 0; i < numFaces; i++) { const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[i]]; v0 = edge->getSourceVertex(); v1 = edge->getTargetVertex(); edge = edge->getNextEdgeOfFace(); v2 = edge->getTargetVertex(); plane = (convexHC->vertices[v1]-convexHC->vertices[v0]).cross(convexHC->vertices[v2]-convexHC->vertices[v0]).normalize(); plane[3] = -plane.dot(convexHC->vertices[v0]); convexPlanes.push_back(plane); } const int numconvexPlanes = convexPlanes.size(); int numpoints = the_voronoi_points.size(); for (i = 0; i < numpoints ; i++) { auto curVoronoiPoint = the_voronoi_points[i]; planes.copyFromArray(convexPlanes); for (j = 0; j < numconvexPlanes; j++) { planes[j][3] += planes[j].dot(type_cast(the_voronoi_points[i])); } maxDistance = SIMD_INFINITY; // sort voronoi points std::sort(sortedVoronoiPoints.begin(), sortedVoronoiPoints.end(), pointCmp(curVoronoiPoint)); for (j=1; j < numpoints; j++) { normal = type_cast(sortedVoronoiPoints[j] - curVoronoiPoint); nlength = normal.length(); if (nlength > maxDistance) break; plane = normal.normalized(); plane[3] = -nlength / btScalar(2.); planes.push_back(plane); getVerticesInsidePlanes(planes, vertices, planeIndices); if (vertices.size() == 0) break; numplaneIndices = planeIndices.size(); if (numplaneIndices != planes.size()) { planeIndicesIter = planeIndices.begin(); for (k=0; k < numplaneIndices; k++) { if (k != *planeIndicesIter) planes[k] = planes[*planeIndicesIter]; planeIndicesIter++; } planes.resize(numplaneIndices); } maxDistance = vertices[0].length(); for (k=1; k < vertices.size(); k++) { distance = vertices[k].length(); if (maxDistance < distance) maxDistance = distance; } maxDistance *= btScalar(2.); } if (vertices.size() == 0) continue; // Clean-up voronoi convex shard vertices and generate edges & faces convexHC->compute(&vertices[0].getX(), sizeof(btVector3), vertices.size(),0.0,0.0); // At this point we have a complete 3D voronoi shard mesh contained in convexHC // Calculate volume and center of mass (Stan Melax volume integration) numFaces = convexHC->faces.size(); btScalar volume = btScalar(0.); btVector3 com(0., 0., 0.); for (j = 0; j < numFaces; j++) { const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]]; v0 = edge->getSourceVertex(); v1 = edge->getTargetVertex(); edge = edge->getNextEdgeOfFace(); v2 = edge->getTargetVertex(); while (v2 != v0) { // Counter-clockwise triangulated voronoi shard mesh faces (v0-v1-v2) and edges here... btScalar vol = convexHC->vertices[v0].triple(convexHC->vertices[v1], convexHC->vertices[v2]); volume += vol; com += vol * (convexHC->vertices[v0] + convexHC->vertices[v1] + convexHC->vertices[v2]); edge = edge->getNextEdgeOfFace(); v1 = v2; v2 = edge->getTargetVertex(); } } com /= volume * btScalar(4.); volume /= btScalar(6.); // Shift all vertices relative to center of mass int numVerts = convexHC->vertices.size(); for (j = 0; j < numVerts; j++) { convexHC->vertices[j] -= com; } // now create our output geometry with indices std::vector<gl::Face3> outer_faces, inner_faces; std::vector<glm::vec3> outer_vertices, inner_vertices; int cur_outer_index = 0, cur_inner_index = 0; for (j = 0; j < numFaces; j++) { const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]]; v0 = edge->getSourceVertex(); v1 = edge->getTargetVertex(); edge = edge->getNextEdgeOfFace(); v2 = edge->getTargetVertex(); // determine if it is an inner or outer face btVector3 cur_plane = (convexHC->vertices[v1] - convexHC->vertices[v0]).cross(convexHC->vertices[v2]-convexHC->vertices[v0]).normalize(); cur_plane[3] = -cur_plane.dot(convexHC->vertices[v0]); bool is_outside = false; for(uint32_t q = 0; q < convexPlanes.size(); q++) { if(is_equal(convexPlanes[q], cur_plane, 0.01f)){ is_outside = true; break;} } std::vector<gl::Face3> *shard_faces = &outer_faces; std::vector<glm::vec3> *shard_vertices = &outer_vertices; int *shard_index = &cur_outer_index; if(!is_outside) { shard_faces = &inner_faces; shard_vertices = &inner_vertices; shard_index = &cur_inner_index; } int face_start_index = *shard_index; // advance index *shard_index += 3; // first 3 verts of n-gon glm::vec3 tmp[] = { type_cast(convexHC->vertices[v0]), type_cast(convexHC->vertices[v1]), type_cast(convexHC->vertices[v2])}; shard_vertices->insert(shard_vertices->end(), tmp, tmp + 3); shard_faces->push_back(gl::Face3(face_start_index, face_start_index + 1, face_start_index + 2)); // add remaining triangles of face (if any) while (true) { edge = edge->getNextEdgeOfFace(); v1 = v2; v2 = edge->getTargetVertex(); // end of n-gon if(v2 == v0) break; shard_vertices->push_back(type_cast(convexHC->vertices[v2])); shard_faces->push_back(gl::Face3(face_start_index, *shard_index - 1, *shard_index)); (*shard_index)++; } } // entry construction gl::Mesh::Entry e0, e1; // outer entry e0.num_vertices = outer_vertices.size(); e0.num_indices = outer_faces.size() * 3; e0.material_index = 0; // inner entry e1.base_index = e0.num_indices; e1.base_vertex = e0.num_vertices; e1.num_vertices = inner_vertices.size(); e1.num_indices = inner_faces.size() * 3; e1.material_index = 1; // create gl::Mesh object for the shard auto inner_geom = gl::Geometry::create(), outer_geom = gl::Geometry::create(); // append verts and indices outer_geom->append_faces(outer_faces); outer_geom->vertices() = outer_vertices; outer_geom->compute_face_normals(); inner_geom->append_faces(inner_faces); inner_geom->append_vertices(inner_vertices); inner_geom->compute_face_normals(); // merge geometries outer_geom->append_vertices(inner_geom->vertices()); outer_geom->append_normals(inner_geom->normals()); outer_geom->append_indices(inner_geom->indices()); outer_geom->faces().insert(outer_geom->faces().end(), inner_geom->faces().begin(), inner_geom->faces().end()); outer_geom->compute_bounding_box(); auto inner_mat = gl::Material::create(); auto m = gl::Mesh::create(outer_geom, gl::Material::create()); m->entries() = {e0, e1}; m->materials().push_back(inner_mat); m->set_position(curVoronoiPoint + type_cast(com)); // m->transform() *= glm::scale(mat4(), vec3(scale_val)); // compute projected texcoords (outside) gl::project_texcoords(the_mesh, m); // compute box mapped texcoords for inside vertices auto &indices = m->geometry()->indices(); auto &vertices = m->geometry()->vertices(); // aabb auto out_aabb = the_mesh->bounding_box(); vec3 aabb_extents = out_aabb.halfExtents() * 2.f; uint32_t base_vertex = m->entries()[1].base_vertex; uint32_t k = m->entries()[1].base_index, kl = k + m->entries()[1].num_indices; for(;k < kl; k += 3) { gl::Face3 f(indices[k] + base_vertex, indices[k] + base_vertex + 1, indices[k] + base_vertex + 2); // normal const vec3 &v0 = vertices[f.a]; const vec3 &v1 = vertices[f.b]; const vec3 &v2 = vertices[f.c]; vec3 n = glm::normalize(glm::cross(v1 - v0, v2 - v0)); float abs_vals[3] = {fabsf(n[0]), fabsf(n[1]), fabsf(n[2])}; // get principal direction int principle_axis = std::distance(abs_vals, std::max_element(abs_vals, abs_vals + 3)); // switch (principle_axis) // { // // X-axis // case 0: // //ZY plane // m->geometry()->texCoords()[f.a] = vec2(v0.z - out_aabb.min.z / aabb_extents.z, // v0.y - out_aabb.min.y / aabb_extents.y); // m->geometry()->texCoords()[f.b] = vec2(v1.z - out_aabb.min.z / aabb_extents.z, // v1.y - out_aabb.min.y / aabb_extents.y); // m->geometry()->texCoords()[f.c] = vec2(v2.z - out_aabb.min.z / aabb_extents.z, // v2.y - out_aabb.min.y / aabb_extents.y); // break; // // // Y-axis // case 1: // // XZ plane // m->geometry()->texCoords()[f.a] = vec2(v0.x - out_aabb.min.x / aabb_extents.x, // v0.z - out_aabb.min.z / aabb_extents.z); // m->geometry()->texCoords()[f.b] = vec2(v1.x - out_aabb.min.x / aabb_extents.x, // v1.z - out_aabb.min.z / aabb_extents.z); // m->geometry()->texCoords()[f.c] = vec2(v2.x - out_aabb.min.x / aabb_extents.x, // v2.z - out_aabb.min.z / aabb_extents.z); // break; // // // Z-axis // case 2: // //XY plane // m->geometry()->texCoords()[f.a] = vec2(v0.x - out_aabb.min.x / aabb_extents.x, // v0.y - out_aabb.min.y / aabb_extents.y); // m->geometry()->texCoords()[f.b] = vec2(v1.x - out_aabb.min.x / aabb_extents.x, // v1.y - out_aabb.min.y / aabb_extents.y); // m->geometry()->texCoords()[f.c] = vec2(v2.x - out_aabb.min.x / aabb_extents.x, // v2.y - out_aabb.min.y / aabb_extents.y); // break; // // default: // break; // } } // push to return structure ret.push_back({m, volume}); } LOG_DEBUG << "Generated " << ret.size() <<" voronoi shards"; return ret; }