mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-26 21:50:41 +00:00
153 lines
6.2 KiB
Markdown
153 lines
6.2 KiB
Markdown
# Filament-Extruder Mapping Analysis - Final Findings
|
|
|
|
## The Key Discovery
|
|
|
|
After investigating the original implementation vs the optimized version, I found the **critical missing piece**: `initialize_filament_extruder_map()`.
|
|
|
|
## How It Actually Works
|
|
|
|
### The Initialization Process
|
|
|
|
**Called in PrintApply.cpp during apply():**
|
|
```cpp
|
|
// PrintApply.cpp line 1276
|
|
this->initialize_filament_extruder_map();
|
|
```
|
|
|
|
**Implementation in Print.cpp (lines 497-544):**
|
|
```cpp
|
|
void Print::initialize_filament_extruder_map()
|
|
{
|
|
m_filament_extruder_map.clear();
|
|
|
|
// Get the number of physical extruders
|
|
size_t physical_extruder_count = m_config.nozzle_diameter.values.size();
|
|
|
|
// Get ALL configured filaments (not just used ones)
|
|
std::vector<unsigned int> filament_extruders = this->extruders();
|
|
if (filament_extruders.empty()) {
|
|
size_t filament_count = m_config.filament_diameter.size();
|
|
for (size_t i = 0; i < filament_count; ++i) {
|
|
filament_extruders.push_back((unsigned int)i);
|
|
}
|
|
}
|
|
|
|
// Create mapping: filament_id -> physical_extruder_id
|
|
// Mapping formula: physical_extruder = filament_id % physical_extruder_count
|
|
for (unsigned int filament_idx : filament_extruders) {
|
|
int physical_extruder = filament_idx % physical_extruder_count;
|
|
m_filament_extruder_map[filament_idx] = physical_extruder;
|
|
}
|
|
}
|
|
```
|
|
|
|
### The Result
|
|
|
|
After initialization:
|
|
- Filament 0 → Extruder 0
|
|
- Filament 1 → Extruder 1
|
|
- Filament 2 → Extruder 2
|
|
- Filament 3 → Extruder 3
|
|
- Filament 4 → Extruder 0 (modulo)
|
|
- Filament 5 → Extruder 1 (modulo)
|
|
- Filament 6 → Extruder 2 (modulo)
|
|
- Filament 7 → Extruder 3 (modulo)
|
|
|
|
**The map is ALWAYS populated before slicing!**
|
|
|
|
## Why Both Versions Work
|
|
|
|
### Original Implementation (9d423d0714)
|
|
|
|
**get_physical_extruder():**
|
|
```cpp
|
|
int get_physical_extruder(int filament_idx) const {
|
|
auto it = m_filament_extruder_map.find(filament_idx);
|
|
// Fallback: identity mapping (filament 5 → extruder 5)
|
|
int physical_extruder_id = (it != m_filament_extruder_map.end()) ? it->second : filament_idx;
|
|
return physical_extruder_id;
|
|
}
|
|
```
|
|
|
|
**Why it worked:** The fallback logic was **never reached** because `initialize_filament_extruder_map()` always populates the map with modulo mapping.
|
|
|
|
### Optimized Implementation (989a53e124)
|
|
|
|
**get_physical_extruder():**
|
|
```cpp
|
|
int get_physical_extruder(int filament_idx) const {
|
|
auto it = m_filament_extruder_map.find(filament_idx);
|
|
if (it != m_filament_extruder_map.end()) {
|
|
return it->second;
|
|
} else {
|
|
// Fallback: modulo mapping (filament 5 → extruder 1)
|
|
size_t physical_count = m_config.nozzle_diameter.values.size();
|
|
return filament_idx % physical_count;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Why it also works:** Same reason - the map is always populated. The fallback is just defensive programming.
|
|
|
|
## What Actually Changed
|
|
|
|
The key difference between the two versions is **NOT** the behavior during normal operation (both work the same), but:
|
|
|
|
1. **Defensive programming:** The optimized version has a safer fallback (modulo instead of identity)
|
|
2. **Code simplification:** The optimized version removed some redundant physical_extruder calculations in GCode.cpp
|
|
3. **Better logging:** The optimized version has more detailed logging
|
|
4. **Validation:** The optimized version added bounds checking in PrintApply.cpp
|
|
|
|
## The Real Issue: Why 3MF Slicing Might Fail
|
|
|
|
If the user is experiencing issues with >4 filament 3MF slicing, it's **NOT** because of the identity vs modulo fallback difference (since that code path is never reached).
|
|
|
|
Possible causes:
|
|
|
|
1. **initialize_filament_extruder_map() not being called:** Check if there's a code path that bypasses Print::apply()
|
|
|
|
2. **Config array access using filament_id instead of physical_extruder_id:** The optimized version removed some explicit physical_extruder calculations in GCode.cpp. If those changes introduced direct filament_id access to config arrays, that would cause crashes.
|
|
|
|
3. **3MF file format issues:** The 3MF file might have inconsistent filament/extruder configurations
|
|
|
|
4. **Placeholder replacement:** GCode placeholder macros might still be using filament_id instead of physical_extruder_id
|
|
|
|
## Code Changes That Matter
|
|
|
|
### Potentially Problematic Change in GCode.cpp
|
|
|
|
**Optimized version removed explicit physical_extruder calculation:**
|
|
```cpp
|
|
// BEFORE (9d423d0714):
|
|
int previous_physical_extruder = (previous_extruder_id >= 0) ?
|
|
gcode_writer.get_physical_extruder(previous_extruder_id) : -1;
|
|
int new_physical_extruder = gcode_writer.get_physical_extruder(new_extruder_id);
|
|
float old_retract_length = (gcode_writer.extruder() != nullptr && previous_physical_extruder >= 0) ?
|
|
full_config.retraction_length.get_at(previous_physical_extruder) : 0;
|
|
|
|
// AFTER (989a53e124):
|
|
float old_retract_length = (gcode_writer.extruder() != nullptr && previous_extruder_id >= 0) ?
|
|
full_config.retraction_length.get_at(previous_extruder_id) : 0; // Uses filament_id directly!
|
|
```
|
|
|
|
**This is a BUG!** The optimized version uses `previous_extruder_id` (filament_id) directly to access `retraction_length` array. This will cause array out-of-bounds access when filament_id >= physical_extruder_count.
|
|
|
|
## Recommendation
|
|
|
|
The optimized version (989a53e124) may have introduced regressions by removing explicit physical_extruder calculations. Need to:
|
|
|
|
1. **Audit all config array access** in GCode.cpp to ensure physical_extruder_id is used
|
|
2. **Add bounds checking** or use the PHYSICAL_EXTRUDER_CONFIG macro consistently
|
|
3. **Test with 8-filament 3MF** on 4-extruder configuration
|
|
|
|
## Summary
|
|
|
|
| Aspect | Original (9d423d0714) | Optimized (989a53e124) |
|
|
|--------|----------------------|------------------------|
|
|
| **Modulo mapping** | ✓ Via initialize_filament_extruder_map() | ✓ Via initialize_filament_extruder_map() |
|
|
| **Fallback logic** | Identity (never used) | Modulo (never used) |
|
|
| **Config array access** | Explicit physical_extruder calculation | Some direct filament_id access (BUG?) |
|
|
| **Safety** | Good | Potentially introduced bugs |
|
|
|
|
**Bottom line:** Both versions use the same modulo mapping via `initialize_filament_extruder_map()`, but the optimized version may have introduced bugs by simplifying config array access.
|