static void AddFracturedPrimitive(DemoEntityManager* const scene, dFloat mass, const dVector& origin, const dVector& size, int xCount, int zCount, dFloat spacing, PrimitiveType type, int materialID, const dMatrix& shapeOffsetMatrix) { // create the shape and visual mesh as a common data to be re used NewtonWorld* const world = scene->GetNewton(); NewtonCollision* const collision = CreateConvexCollision(world, shapeOffsetMatrix, size, type, materialID); // create a newton mesh from the collision primitive NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision); // apply a material map int externalMaterial = LoadTexture("reljef.tga"); //int internalMaterial = LoadTexture("KAMEN-stup.tga"); int internalMaterial = LoadTexture("concreteBrick.tga"); dMatrix aligmentUV(dGetIdentityMatrix()); NewtonMeshApplyBoxMapping(mesh, externalMaterial, externalMaterial, externalMaterial, &aligmentUV[0][0]); // create a newton mesh from the collision primitive VoronoidEffect fracture(world, mesh, internalMaterial); DemoMesh* const visualMesh = new DemoMesh(mesh); dFloat startElevation = 100.0f; dMatrix matrix(dGetIdentityMatrix()); for (int i = 0; i < xCount; i++) { dFloat x = origin.m_x + (i - xCount / 2) * spacing; for (int j = 0; j < zCount; j++) { dFloat z = origin.m_z + (j - zCount / 2) * spacing; matrix.m_posit.m_x = x; matrix.m_posit.m_z = z; dVector floor(FindFloor(world, dVector(matrix.m_posit.m_x, startElevation, matrix.m_posit.m_z, 0.0f), 2.0f * startElevation)); matrix.m_posit.m_y = floor.m_y + 1.0f; SimpleFracturedEffectEntity::AddFracturedEntity(scene, visualMesh, collision, fracture, matrix.m_posit); } } // do not forget to release the assets NewtonMeshDestroy(mesh); visualMesh->Release(); NewtonDestroyCollision(collision); }
int main(int argc, char **argv) { /* We choose to handle simple command line input */ int num_threads(0), box_length(0); try { if (argc == 5) { if (strcmp(argv[1], "-np") == 0 && strcmp(argv[3], "-bl") == 0) { sscanf(argv[2], "%d", &num_threads); sscanf(argv[4], "%d", &box_length); } else throw std::runtime_error("Incorrect arugments"); } else throw std::runtime_error("Incorrect number of arguments"); } catch(std::runtime_error &error) { std::cout << error.what() << std::endl; std::cout << "Use the form :: ./regulus -np X -bl Y \n"; return -1; } /* ... And we then build a point set to triangulate... */ unsigned long int num_points = std::pow(box_length, 3); std::vector<mesh> meshes; { std::vector<point> tmp_point_buff; tmp_point_buff.reserve(num_points); write_sorted_set(tmp_point_buff, num_points, box_length); auto m = num_points % num_threads; auto ppp = (num_points - m) / num_threads; for (int i = 0; i < num_threads; ++i) { unsigned long int num_per_tetra = 0; if (i != num_threads - 1) num_per_tetra = ppp; else num_per_tetra = ppp + m; meshes.emplace_back(num_per_tetra); /* Allocate root points */ auto tl = 3 * (box_length - 1); meshes[i].p_buffer.emplace_back(0, 0, 0); meshes[i].p_buffer.emplace_back(tl, 0, 0); meshes[i].p_buffer.emplace_back(0, tl, 0); meshes[i].p_buffer.emplace_back(0, 0, tl); meshes[i].p_position += 4; /* Allocate root tetrahedron */ new(meshes[i].t_position) tetra(&meshes[i].p_buffer[0], &meshes[i].p_buffer[1], &meshes[i].p_buffer[2], &meshes[i].p_buffer[3]); meshes[i].m_position = meshes[i].t_position; ++meshes[i].t_position; /* Copy partitioned points */ for (unsigned long int j = 0; j < num_per_tetra; ++j) { auto &cpy = tmp_point_buff[i*ppp + j]; meshes[i].p_buffer.emplace_back(cpy.x, cpy.y, cpy.z); } if (verbose >= 3) { std::cout << "\nthread : " << i << std::endl; for (auto it = meshes[i].p_buffer.begin(); it < meshes[i].p_buffer.end(); ++it) std::cout << *it << std::endl; } std::cout << std::endl; } } /* This is the crux of regulus We begin the triangulation */ double start_time = get_wall_time(); std::vector<std::thread> threads; for (int i = 0; i < num_threads; ++i) { threads.emplace_back([&meshes, i](void)->void { std::vector<std::pair<tetra*, unsigned int>> leaves; leaves.reserve(512); std::vector<tetra*> pile; pile.reserve(2048); point *p = meshes[i].p_buffer.data(); for (unsigned long int j = 5; j < meshes[i].p_buffer.size(); ++j) { if (verbose >= 1) std::cout << "\niterative index : " << j - 4 << std::endl; walk(leaves, p + j, meshes[i].m_position, &*(meshes[i].t_buffer.begin())); fracture(meshes[i], leaves, pile, p + j); delaunay(meshes[i], pile); leaves.clear(); pile.clear(); } }); } for (auto &t : threads) t.join(); unsigned long int tot_num_tetra = 0; for (auto &m : meshes) tot_num_tetra += m.num_tetra; double end_time = get_wall_time(); std::cout << "\nTotal number of tetrahedra triangulated : " << tot_num_tetra << std::endl; std::cout<< "\nTriangulated " << num_points << " points in " << end_time - start_time << " seconds" << std::endl; std::cout << num_points / ((end_time - start_time) * num_threads) << " points per second per thread" << std::endl; return 0; }