std::string FffProcessor::getAllSettingsString(MeshGroup& meshgroup, bool first_meshgroup) { std::stringstream sstream; if (first_meshgroup) { sstream << getAllLocalSettingsString(); // global settings sstream << " -g"; } else { sstream << " --next"; } sstream << meshgroup.getAllLocalSettingsString(); for (int extruder_nr = 0; extruder_nr < meshgroup.getExtruderCount(); extruder_nr++) { ExtruderTrain* train = meshgroup.getExtruderTrain(extruder_nr); sstream << " -e" << extruder_nr << train->getAllLocalSettingsString(); } for (unsigned int mesh_idx = 0; mesh_idx < meshgroup.meshes.size(); mesh_idx++) { Mesh& mesh = meshgroup.meshes[mesh_idx]; sstream << " -e" << mesh.getSettingAsIndex("extruder_nr") << " -l \"" << mesh_idx << "\"" << mesh.getAllLocalSettingsString(); } sstream << "\n"; return sstream.str(); }
void PrimeTower::initConfigs(MeshGroup* meshgroup, std::vector<RetractionConfig>& retraction_config_per_extruder) { extruder_count = meshgroup->getSettingAsCount("machine_extruder_count"); for (int extr = 0; extr < extruder_count; extr++) { config_per_extruder.emplace_back(PrintFeatureType::Support);// so that visualization in the old Cura still works (TODO) } for (int extr = 0; extr < extruder_count; extr++) { ExtruderTrain* train = meshgroup->getExtruderTrain(extr); config_per_extruder[extr].init(train->getSettingInMillimetersPerSecond("speed_prime_tower"), train->getSettingInMillimetersPerSecond("acceleration_prime_tower"), train->getSettingInMillimetersPerSecond("jerk_prime_tower"), train->getSettingInMicrons("prime_tower_line_width"), train->getSettingInPercentage("prime_tower_flow")); } }
void PrimeTower::setConfigs(MeshGroup* meshgroup, std::vector<RetractionConfig>& retraction_config_per_extruder, int layer_thickness) { extruder_count = meshgroup->getSettingAsCount("machine_extruder_count"); for (int extr = 0; extr < extruder_count; extr++) { ExtruderTrain* train = meshgroup->getExtruderTrain(extr); GCodePathConfig& conf = config_per_extruder[extr]; conf.setSpeed(train->getSettingInMillimetersPerSecond("speed_prime_tower")); conf.setLineWidth(train->getSettingInMicrons("prime_tower_line_width")); conf.setFlow(train->getSettingInPercentage("prime_tower_flow")); conf.setLayerHeight(layer_thickness); } }
void Raft::generate(SliceDataStorage& storage, int distance) { assert(storage.raftOutline.size() == 0 && "Raft polygon isn't generated yet, so should be empty!"); storage.raftOutline = storage.getLayerOutlines(0, true).offset(distance, ClipperLib::jtRound); ExtruderTrain* train = storage.meshgroup->getExtruderTrain(storage.getSettingAsIndex("adhesion_extruder_nr")); const int shield_line_width_layer0 = train->getSettingInMicrons("skirt_brim_line_width"); if (storage.draft_protection_shield.size() > 0) { Polygons draft_shield_raft = storage.draft_protection_shield.offset(shield_line_width_layer0) // start half a line width outside shield .difference(storage.draft_protection_shield.offset(-distance - shield_line_width_layer0 / 2, ClipperLib::jtRound)); // end distance inside shield storage.raftOutline = storage.raftOutline.unionPolygons(draft_shield_raft); } if (storage.oozeShield.size() > 0 && storage.oozeShield[0].size() > 0) { const Polygons& ooze_shield = storage.oozeShield[0]; Polygons ooze_shield_raft = ooze_shield.offset(shield_line_width_layer0) // start half a line width outside shield .difference(ooze_shield.offset(-distance - shield_line_width_layer0 / 2, ClipperLib::jtRound)); // end distance inside shield storage.raftOutline = storage.raftOutline.unionPolygons(ooze_shield_raft); } coord_t smoothing = train->getSettingInMicrons("raft_smoothing"); storage.raftOutline = storage.raftOutline.offset(smoothing, ClipperLib::jtRound).offset(-smoothing, ClipperLib::jtRound); // remove small holes and smooth inward corners }
bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeeper, SliceDataStorage& storage) /// slices the model { Progress::messageProgressStage(Progress::Stage::SLICING, &timeKeeper); storage.model_min = meshgroup->min(); storage.model_max = meshgroup->max(); storage.model_size = storage.model_max - storage.model_min; log("Slicing model...\n"); int initial_layer_thickness = getSettingInMicrons("layer_height_0"); if(initial_layer_thickness <= 0) //Initial layer height of 0 is not allowed. Negative layer height is nonsense. { logError("Initial layer height %i is disallowed.",initial_layer_thickness); return false; } int layer_thickness = getSettingInMicrons("layer_height"); if(layer_thickness <= 0) //Layer height of 0 is not allowed. Negative layer height is nonsense. { logError("Layer height %i is disallowed.",layer_thickness); return false; } int initial_slice_z = initial_layer_thickness - layer_thickness / 2; int layer_count = (storage.model_max.z - initial_slice_z) / layer_thickness + 1; if(layer_count <= 0) //Model is shallower than layer_height_0, so not even the first layer is sliced. Return an empty model then. { return true; //This is NOT an error state! } std::vector<Slicer*> slicerList; for(unsigned int mesh_idx = 0; mesh_idx < meshgroup->meshes.size(); mesh_idx++) { Mesh& mesh = meshgroup->meshes[mesh_idx]; Slicer* slicer = new Slicer(&mesh, initial_slice_z, layer_thickness, layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching")); slicerList.push_back(slicer); /* for(SlicerLayer& layer : slicer->layers) { //Reporting the outline here slows down the engine quite a bit, so only do so when debugging. sendPolygons("outline", layer_nr, layer.z, layer.polygonList); sendPolygons("openoutline", layer_nr, layer.openPolygonList); } */ Progress::messageProgress(Progress::Stage::SLICING, mesh_idx + 1, meshgroup->meshes.size()); } log("Layer count: %i\n", layer_count); meshgroup->clear();///Clear the mesh face and vertex data, it is no longer needed after this point, and it saves a lot of memory. Progress::messageProgressStage(Progress::Stage::PARTS, &timeKeeper); //carveMultipleVolumes(storage.meshes); generateMultipleVolumesOverlap(slicerList); // TODO!!! dont generate multi volume overlap with infill meshes! storage.meshes.reserve(slicerList.size()); // causes there to be no resize in meshes so that the pointers in sliceMeshStorage._config to retraction_config don't get invalidated. for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++) { storage.meshes.emplace_back(&meshgroup->meshes[meshIdx]); // new mesh in storage had settings from the Mesh SliceMeshStorage& meshStorage = storage.meshes.back(); Mesh& mesh = storage.meshgroup->meshes[meshIdx]; createLayerParts(meshStorage, slicerList[meshIdx], mesh.getSettingBoolean("meshfix_union_all"), mesh.getSettingBoolean("meshfix_union_all_remove_holes")); delete slicerList[meshIdx]; bool has_raft = meshStorage.getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::RAFT; //Add the raft offset to each layer. for(unsigned int layer_nr=0; layer_nr<meshStorage.layers.size(); layer_nr++) { SliceLayer& layer = meshStorage.layers[layer_nr]; meshStorage.layers[layer_nr].printZ += getSettingInMicrons("layer_height_0") - initial_slice_z; if (has_raft) { ExtruderTrain* train = storage.meshgroup->getExtruderTrain(getSettingAsIndex("adhesion_extruder_nr")); layer.printZ += train->getSettingInMicrons("raft_base_thickness") + train->getSettingInMicrons("raft_interface_thickness") + train->getSettingAsCount("raft_surface_layers") * getSettingInMicrons("raft_surface_thickness") + train->getSettingInMicrons("raft_airgap") - train->getSettingInMicrons("layer_0_z_overlap"); // shift all layers (except 0) down if (layer_nr == 0) { layer.printZ += train->getSettingInMicrons("layer_0_z_overlap"); // undo shifting down of first layer } } if (layer.parts.size() > 0 || (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL && layer.openPolyLines.size() > 0) ) { meshStorage.layer_nr_max_filled_layer = layer_nr; // last set by the highest non-empty layer } if (CommandSocket::isInstantiated()) { CommandSocket::getInstance()->sendLayerInfo(layer_nr, layer.printZ, layer_nr == 0? getSettingInMicrons("layer_height_0") : getSettingInMicrons("layer_height")); } } Progress::messageProgress(Progress::Stage::PARTS, meshIdx + 1, slicerList.size()); } return true; }
void CommandSocket::handleObjectList(cura::proto::ObjectList* list, const google::protobuf::RepeatedPtrField<cura::proto::Extruder> settings_per_extruder_train) { if (list->objects_size() <= 0) { return; } FMatrix3x3 matrix; //private_data->object_count = 0; //private_data->object_ids.clear(); private_data->objects_to_slice.push_back(std::make_shared<MeshGroup>(FffProcessor::getInstance())); MeshGroup* meshgroup = private_data->objects_to_slice.back().get(); // load meshgroup settings for (auto setting : list->settings()) { meshgroup->setSetting(setting.name(), setting.value()); } { // load extruder settings for (int extruder_nr = 0; extruder_nr < FffProcessor::getInstance()->getSettingAsCount("machine_extruder_count"); extruder_nr++) { // initialize remaining extruder trains and load the defaults ExtruderTrain* train = meshgroup->createExtruderTrain(extruder_nr); // create new extruder train objects or use already existing ones SettingRegistry::getInstance()->loadExtruderJSONsettings(extruder_nr, train); } for (auto extruder : settings_per_extruder_train) { int extruder_nr = extruder.id(); ExtruderTrain* train = meshgroup->createExtruderTrain(extruder_nr); // create new extruder train objects or use already existing ones for (auto setting : extruder.settings().settings()) { train->setSetting(setting.name(), setting.value()); } } } for (auto object : list->objects()) { int bytes_per_face = BYTES_PER_FLOAT * FLOATS_PER_VECTOR * VECTORS_PER_FACE; int face_count = object.vertices().size() / bytes_per_face; if (face_count <= 0) { logWarning("Got an empty mesh, ignoring it!"); continue; } DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR("solid Cura_out\n"); // Check to which extruder train this object belongs int extruder_train_nr = 0; // assume extruder 0 if setting wasn't supplied for (auto setting : object.settings()) { if (setting.name() == "extruder_nr") { extruder_train_nr = std::stoi(setting.value()); break; } } SettingsBase* extruder_train = meshgroup->getExtruderTrain(extruder_train_nr); meshgroup->meshes.push_back(extruder_train); //Construct a new mesh (with the corresponding extruder train as settings parent object) and put it into MeshGroup's mesh list. Mesh& mesh = meshgroup->meshes.back(); for (int i = 0; i < face_count; ++i) { //TODO: Apply matrix std::string data = object.vertices().substr(i * bytes_per_face, bytes_per_face); const FPoint3* float_vertices = reinterpret_cast<const FPoint3*>(data.data()); Point3 verts[3]; verts[0] = matrix.apply(float_vertices[0]); verts[1] = matrix.apply(float_vertices[1]); verts[2] = matrix.apply(float_vertices[2]); mesh.addFace(verts[0], verts[1], verts[2]); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" facet normal -1 0 0\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" outer loop\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" vertex "<<INT2MM(verts[0].x) <<" " << INT2MM(verts[0].y) <<" " << INT2MM(verts[0].z) << "\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" vertex "<<INT2MM(verts[1].x) <<" " << INT2MM(verts[1].y) <<" " << INT2MM(verts[1].z) << "\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" vertex "<<INT2MM(verts[2].x) <<" " << INT2MM(verts[2].y) <<" " << INT2MM(verts[2].z) << "\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" endloop\n"); DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR(" endfacet\n"); } DEBUG_OUTPUT_OBJECT_STL_THROUGH_CERR("endsolid Cura_out\n"); for (auto setting : object.settings()) { mesh.setSetting(setting.name(), setting.value()); } mesh.finish(); } private_data->object_count++; meshgroup->finalize(); }