diff --git a/BUILD.md b/BUILD.md deleted file mode 100644 index 6d5920c6c0..0000000000 --- a/BUILD.md +++ /dev/null @@ -1,202 +0,0 @@ -# Building OrcaSlicer with ZAA on macOS - -A step-by-step guide to building OrcaSlicer from source on macOS. No prior experience with building software required. - -## What You'll Need - -- A Mac running macOS 11.3 (Big Sur) or later -- About 15 GB of free disk space -- An internet connection -- About 1-2 hours for the first build (mostly waiting) - -## Step 1: Open Terminal - -Press **Cmd + Space**, type **Terminal**, and press Enter. A window with a command prompt will appear. All commands below are typed into this window. - -## Step 2: Install Xcode Command Line Tools - -This installs the compiler and basic development tools. - -```bash -xcode-select --install -``` - -A dialog will pop up. Click **Install** and wait for it to finish (a few minutes). - -To verify it worked: - -```bash -xcode-select -p -git --version -``` - -You should see a path like `/Library/Developer/CommandLineTools` and a git version. Both git and the C++ compiler are included in the Command Line Tools. - -## Step 3: Install Homebrew - -[Homebrew](https://brew.sh) is a package manager that makes it easy to install developer tools on macOS. - -```bash -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -``` - -Follow the prompts. When it finishes, it will tell you to run one or two commands to add Homebrew to your PATH. **Run those commands** — they look something like: - -```bash -echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile -eval "$(/opt/homebrew/bin/brew shellenv)" -``` - -To verify: - -```bash -brew --version -``` - -## Step 4: Install CMake - -CMake is the build system OrcaSlicer uses. - -```bash -brew install cmake -``` - -To verify: - -```bash -cmake --version -``` - -You need version 3.13 or later (anything recent from Homebrew will work). - -## Step 5: Clone the Repository - -Choose where you want the source code. For example, in your home directory: - -```bash -cd ~ -git clone https://github.com/mnott/OrcaSlicer.git -cd OrcaSlicer -``` - -If you want the ZAA feature branch: - -```bash -git checkout feature/zaa-contouring -``` - -## Step 6: Build - -The `build.sh` script handles everything. For a first-time build: - -```bash -chmod +x build.sh -./build.sh --full -``` - -This does three things: -1. **Builds dependencies** (Boost, wxWidgets, OpenSSL, etc.) — takes 30-60 minutes the first time -2. **Configures CMake** — sets up the build system -3. **Builds OrcaSlicer** — compiles the application - -Go get a coffee. The dependency step only needs to run once. - -### After the first build - -For subsequent builds (after making code changes), just run: - -```bash -./build.sh -``` - -This does an incremental build — only recompiles what changed. Usually takes 1-5 minutes. - -### Other build options - -```bash -./build.sh --help # Show all options -./build.sh --clean # Clean rebuild (if something is broken) -./build.sh --deps # Rebuild dependencies only -./build.sh --configure # Reconfigure CMake only -``` - -## Step 7: Run OrcaSlicer - -After a successful build, the script prints the app location. You can run it with: - -```bash -open build/arm64/src/RelWithDebInfo/OrcaSlicer.app -``` - -Or find `OrcaSlicer.app` in Finder and double-click it. - -## Troubleshooting - -### "CMake not found" - -Make sure Homebrew is in your PATH (see Step 3), then `brew install cmake`. - -### "No rule to make target" or CMake generator errors - -Your build directory may have been configured with a different generator. Clean and reconfigure: - -```bash -./build.sh --clean --full -``` - -### Build fails during dependencies - -Some deps need a lot of memory. Close other applications and try again. If a specific dependency fails, check if you have the latest Xcode Command Line Tools: - -```bash -softwareupdate --list -``` - -### wxWidgets "hardcoded path" errors - -wxWidgets bakes the installation path into its config files. If you move the source directory after building deps, you need to rebuild them: - -```bash -./build.sh --deps -./build.sh --clean -``` - -### "Permission denied" on build.sh - -```bash -chmod +x build.sh -``` - -### Apple Silicon (M1/M2/M3/M4) vs Intel - -The build script auto-detects your architecture. If you need to specify it explicitly: - -```bash -./build.sh --full --arch arm64 # Apple Silicon -./build.sh --full --arch x86_64 # Intel -``` - -## Project Structure - -``` -OrcaSlicer/ -├── src/ -│ ├── libslic3r/ # Core slicing engine -│ │ ├── ContourZ.cpp # ZAA raycasting algorithm -│ │ └── ... -│ └── slic3r/GUI/ # User interface -├── deps/ # External dependencies -├── build/ # Build output (created by build.sh) -│ └── arm64/ -│ └── src/RelWithDebInfo/ -│ └── OrcaSlicer.app -├── docs/ -│ └── ZAA.md # ZAA feature documentation -├── build.sh # Build script (this guide uses it) -├── BUILD.md # This file -└── build_release_macos.sh # Official release build script -``` - -## ZAA (Z Anti-Aliasing) - -See [docs/ZAA.md](docs/ZAA.md) for details on the Z Anti-Aliasing feature. In short: enable **Z contouring** in Print Settings > Quality to get smoother curved surfaces. diff --git a/build.sh b/build.sh deleted file mode 100755 index 42332937b3..0000000000 --- a/build.sh +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/env bash -# OrcaSlicer Build Script (macOS) -# Handles the full build lifecycle: deps, configure, build -# -# Usage: -# ./build.sh # Incremental build (after initial setup) -# ./build.sh --full # Full build from scratch (deps + configure + build) -# ./build.sh --deps # Build dependencies only -# ./build.sh --configure # Run CMake configure only -# ./build.sh --clean # Remove build dir and rebuild -# ./build.sh --help # Show all options - -set -e -set -o pipefail - -# ── Configuration ────────────────────────────────────────────── - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ARCH="${ARCH:-$(uname -m)}" -BUILD_CONFIG="${BUILD_CONFIG:-RelWithDebInfo}" -OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET:-11.3}" -NCPU=$(sysctl -n hw.ncpu 2>/dev/null || echo 4) - -BUILD_DIR="${SCRIPT_DIR}/build/${ARCH}" -DEPS_DIR="${SCRIPT_DIR}/deps" -DEPS_BUILD_DIR="${DEPS_DIR}/build/${ARCH}" -DEPS_INSTALL_DIR="${DEPS_BUILD_DIR}/OrcaSlicer_dep" - -# CMake 4.x compatibility -CMAKE_VERSION=$(cmake --version 2>/dev/null | head -1 | sed 's/[^0-9]*\([0-9]*\).*/\1/') -CMAKE_COMPAT="" -if [ "${CMAKE_VERSION:-3}" -ge 4 ] 2>/dev/null; then - CMAKE_COMPAT="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" -fi - -# ── Colors ───────────────────────────────────────────────────── - -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -BLUE='\033[0;34m' -BOLD='\033[1m' -NC='\033[0m' - -info() { echo -e "${BLUE}▸${NC} $*"; } -ok() { echo -e "${GREEN}✓${NC} $*"; } -warn() { echo -e "${YELLOW}⚠${NC} $*"; } -err() { echo -e "${RED}✗${NC} $*"; } - -# ── Parse Arguments ──────────────────────────────────────────── - -DO_DEPS=false -DO_CONFIGURE=false -DO_BUILD=true -DO_CLEAN=false -DO_FULL=false - -while [[ $# -gt 0 ]]; do - case $1 in - --full) DO_FULL=true; shift ;; - --deps) DO_DEPS=true; DO_BUILD=false; shift ;; - --configure) DO_CONFIGURE=true; DO_BUILD=false; shift ;; - --clean) DO_CLEAN=true; shift ;; - --arch) ARCH="$2"; shift 2 ;; - --config) BUILD_CONFIG="$2"; shift 2 ;; - --help|-h) - echo "OrcaSlicer Build Script (macOS)" - echo "" - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Build modes:" - echo " (no flags) Incremental build (fastest, use after initial setup)" - echo " --full Full build from scratch: deps → configure → build" - echo " --deps Build dependencies only (takes 30-60 min first time)" - echo " --configure Run CMake configure only" - echo " --clean Remove build directory, then rebuild" - echo "" - echo "Options:" - echo " --arch ARCH Architecture: arm64, x86_64 (default: $(uname -m))" - echo " --config CFG Build config: Release, RelWithDebInfo, Debug" - echo " (default: RelWithDebInfo)" - echo "" - echo "Examples:" - echo " $0 --full # First-time build (do this first!)" - echo " $0 # Quick rebuild after code changes" - echo " $0 --clean # Clean rebuild if something is broken" - echo "" - echo "Prerequisites: Xcode Command Line Tools, CMake 3.13+" - echo " xcode-select --install" - echo " brew install cmake" - exit 0 - ;; - *) - err "Unknown option: $1 (use --help)" - exit 1 - ;; - esac -done - -# --full implies all steps -if [ "$DO_FULL" = true ]; then - DO_DEPS=true - DO_CONFIGURE=true - DO_BUILD=true -fi - -# ── Preflight Checks ────────────────────────────────────────── - -echo "" -echo -e "${BOLD}OrcaSlicer Build${NC}" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo " Architecture: ${ARCH}" -echo " Config: ${BUILD_CONFIG}" -echo " CPU cores: ${NCPU}" -echo " CMake: $(cmake --version 2>/dev/null | head -1 || echo 'NOT FOUND')" -[ -n "$CMAKE_COMPAT" ] && echo " CMake compat: 4.x → policy 3.5" -echo "" - -# Check prerequisites -if ! command -v cmake &>/dev/null; then - err "CMake not found. Install it with: brew install cmake" - exit 1 -fi - -if ! command -v git &>/dev/null; then - err "Git not found. Install Xcode Command Line Tools: xcode-select --install" - exit 1 -fi - -if ! xcode-select -p &>/dev/null; then - err "Xcode Command Line Tools not found. Install: xcode-select --install" - exit 1 -fi - -# ── Clean ────────────────────────────────────────────────────── - -if [ "$DO_CLEAN" = true ]; then - warn "Removing build directory: ${BUILD_DIR}" - rm -rf "${BUILD_DIR}" - ok "Clean complete" - echo "" -fi - -# ── Build Dependencies ───────────────────────────────────────── - -if [ "$DO_DEPS" = true ]; then - info "Building dependencies (this takes a while the first time)..." - mkdir -p "${DEPS_INSTALL_DIR}" - cd "${DEPS_BUILD_DIR}" - - cmake "${DEPS_DIR}" \ - -G "Unix Makefiles" \ - -DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \ - -DCMAKE_OSX_ARCHITECTURES:STRING="${ARCH}" \ - -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \ - ${CMAKE_COMPAT} - - cmake --build . --config "${BUILD_CONFIG}" --target deps -j"${NCPU}" - - ok "Dependencies built" - echo "" -fi - -# ── Configure ────────────────────────────────────────────────── - -if [ "$DO_CONFIGURE" = true ] || { [ "$DO_BUILD" = true ] && [ ! -f "${BUILD_DIR}/Makefile" ] && [ ! -f "${BUILD_DIR}/build.ninja" ]; }; then - info "Configuring CMake..." - mkdir -p "${BUILD_DIR}" - cd "${BUILD_DIR}" - - cmake "${SCRIPT_DIR}" \ - -G "Unix Makefiles" \ - -DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \ - -DCMAKE_OSX_ARCHITECTURES="${ARCH}" \ - -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \ - ${CMAKE_COMPAT} - - ok "CMake configured" - echo "" -fi - -# ── Build ────────────────────────────────────────────────────── - -if [ "$DO_BUILD" = true ]; then - if [ ! -d "${BUILD_DIR}" ]; then - err "Build directory not found: ${BUILD_DIR}" - err "Run '$0 --full' for a first-time build" - exit 1 - fi - - info "Building OrcaSlicer..." - cd "${SCRIPT_DIR}" - - cmake --build "${BUILD_DIR}" \ - --config "${BUILD_CONFIG}" \ - --target OrcaSlicer \ - -j"${NCPU}" - - echo "" - echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - ok "Build complete!" - echo "" - echo " App: ${BUILD_DIR}/src/${BUILD_CONFIG}/OrcaSlicer.app" - echo "" - echo " Run: open \"${BUILD_DIR}/src/${BUILD_CONFIG}/OrcaSlicer.app\"" - echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -fi diff --git a/docs/ZAA.md b/docs/ZAA.md deleted file mode 100644 index dbeecc6548..0000000000 --- a/docs/ZAA.md +++ /dev/null @@ -1,41 +0,0 @@ -# Z Anti-Aliasing (ZAA) — Z Contouring - -ZAA eliminates stair-stepping on curved and sloped top surfaces by adjusting the Z height of each extrusion point to follow the actual 3D model surface. - -Instead of printing flat horizontal layers, ZAA raycasts each point of the toolpath against the original mesh and micro-adjusts its Z coordinate to match the true surface geometry. The result is visibly smoother surfaces on domes, chamfers, and shallow slopes — without post-processing. - -This is a port of the ZAA implementation from [BambuStudio-ZAA](https://github.com/adob/BambuStudio-ZAA) by adob. - -## Configuration - -ZAA adds five settings under **Print Settings > Quality**: - -| Setting | Type | Default | Description | -|---------|------|---------|-------------| -| `zaa_enabled` | bool | off | Master enable/disable switch | -| `zaa_min_z` | float | 0.06 mm | Minimum Z layer height; also controls the slicing plane offset | -| `zaa_minimize_perimeter_height` | float | 35° | Reduce perimeter heights on slopes below this angle (0 = disabled) | -| `zaa_dont_alternate_fill_direction` | bool | off | Keep fill direction consistent instead of alternating per layer | -| `zaa_region_disable` | bool | off | Disable ZAA for a specific print region/material | - -## How It Works - -1. The slicer slices normally, then runs a **posContouring** step on each layer. -2. `ContourZ.cpp` raycasts every extrusion point vertically against the source mesh. -3. Each point's Z is adjusted to the mesh intersection, converting flat `Polyline` paths into `Polyline3` paths that carry per-point Z coordinates. -4. The G-code writer emits the adjusted Z values, so the printer follows the true surface. - -## Key Implementation Details - -- **Core algorithm**: `src/libslic3r/ContourZ.cpp` (~330 lines) -- **3D geometry**: `Point3`, `Line3`, `Polyline3`, `MultiPoint3` extend the existing 2D types -- **Pipeline step**: `posContouring` in `PrintObject.cpp`, runs after perimeter/infill generation -- **G-code output**: `GCode.cpp` writes per-point Z when `path.z_contoured` is set -- **Arc fitting**: Templated to work with both 2D and 3D geometry -- **ExtrusionPath change**: `polyline` field changed from `Polyline` to `Polyline3` - -## Testing - -1. Load a model with curved top surfaces (spheres, domes, chamfered edges) -2. Enable **Z contouring** in Print Settings > Quality -3. Slice and inspect the G-code — Z values should vary within each layer on contoured surfaces diff --git a/src/libslic3r/ContourZ.cpp b/src/libslic3r/ContourZ.cpp index 13a266573f..0182b35aad 100644 --- a/src/libslic3r/ContourZ.cpp +++ b/src/libslic3r/ContourZ.cpp @@ -15,49 +15,25 @@ namespace Slic3r { static void contour_extrusion_entity(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntity *extr); -// static double lowest_z_within_distance(const Vec3d &normal, double dist) { -// const Vec3d p(0.0, 0.0, 0.0); -// Eigen::Vector3d n_unit = normal.normalized(); -// Eigen::Vector3d z_hat(0.0, 0.0, 1.0); - -// // Project the negative z-direction into the tangent plane -// Eigen::Vector3d v_dir = -z_hat + (z_hat.dot(n_unit)) * n_unit; - -// double norm_v = v_dir.norm(); -// if (norm_v == 0.0) { -// // Surface is horizontal, cannot go lower in z within tangent plane -// return p.z(); -// } - -// Eigen::Vector3d v = dist * v_dir / norm_v; -// Eigen::Vector3d q = p + v; -// return q.z(); -// } - -static double follow_slope_down(double angle_rad, double dist) { +static double follow_slope_down(double angle_rad, double dist) +{ return -dist * std::sin(angle_rad); } -static double slope_from_normal(const Eigen::Vector3d& normal) { +static double slope_from_normal(const Eigen::Vector3d& normal) +{ // Ensure the normal is normalized Eigen::Vector3d n = normal.normalized(); // Compute angle between normal and z-axis double angle_rad = std::acos(std::abs(n.z())); // angle between normal and vertical return angle_rad; - - // calculate fall over dist - // double dist = 0.2; - // double z_dist = lowest_z(angle_rad, dist); - // printf("fall %f vs %f\n", z_dist, lowest_z_within_distance(normal, dist)); - - // double angle_deg = angle_rad * 180.0 / M_PI; - // return angle_deg; } // const int LINE = 180; -static bool contour_extrusion_path(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionPath &path) { +static bool contour_extrusion_path(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionPath &path) +{ if (region->region().config().zaa_region_disable) { return false; } @@ -74,19 +50,11 @@ static bool contour_extrusion_path(LayerRegion *region, const sla::IndexedMesh & double resolution_mm = 0.1; coordf_t height = layer->height; - // std::cout << "LAYER " << (layer->id()+1) << std::endl; - // std::cout << "PRINT Z " << layer->print_z << std::endl; - // std::cout << "LAYER HEIGHT " << height << std::endl; - // std::cout << "EXTRUSION HEIGHT " << path.height << std::endl; - // std::cout << "EXTRUSION WIDTH " << path.width << std::endl; - // std::cout << "EXTRUSION ROLE: " << ExtrusionEntity::role_to_string(path.role()) << std::endl; - // std::cout << "FIRST POINT: " << path.polyline.first_point() << std::endl; double minimize_perimeter_height_angle = region->region().config().zaa_minimize_perimeter_height; Pointf3s contoured_points; bool was_contoured = false; - // bool is_perimeter = path.role() == erExternalPerimeter || path.role() == erPerimeter || path.role() == erOverhangPerimeter; for (Points3::const_iterator it = points.begin(); it != points.end()-1; ++it) { Vec2d p1d(unscale_(it->x()), unscale_(it->y())); @@ -195,13 +163,15 @@ static void contour_extrusion_loop(LayerRegion *region, const sla::IndexedMesh & } } -static void contour_extrusion_entitiy_collection(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntityCollection &collection) { +static void contour_extrusion_entitiy_collection(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntityCollection &collection) +{ for (ExtrusionEntity *entity : collection.entities) { contour_extrusion_entity(region, mesh, entity); } } -static void contour_extrusion_entity(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntity *extr) { +static void contour_extrusion_entity(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntity *extr) +{ const ExtrusionPathSloped *sloped = dynamic_cast(extr); if (sloped != nullptr) { throw RuntimeError("ExtrusionPathSloped not implemented"); @@ -253,81 +223,11 @@ static void handle_extrusion_collection(LayerRegion *region, const sla::IndexedM } } -// static void find_point(ExtrusionPath &path, const std::string &path_info) { -// Points3 &points = path.polyline.points; - -// size_t i = 0; -// for (Points3::const_iterator it = points.begin(); it != points.end()-1; ++it) { -// if (it->x() == -883971 && it->y() == 979001) { -// std::cout << "FOUND POINT " << ExtrusionEntity::role_to_string(path.role()) << " at path " << path_info << "[" + std::to_string(i) + "]" << std::endl; -// } -// i++; -// } -// } - -// static void find_point(ExtrusionLoop &loop, const std::string &path_info) { -// size_t i = 0; -// for (ExtrusionPath &path : loop.paths) { -// find_point(path, path_info + "[" + std::to_string(i) + "]"); -// i++; -// } -// } - -// static void find_point(ExtrusionEntity &extr, const std::string &path); - -// static void find_point(ExtrusionEntityCollection &collection, const std::string &path) { -// size_t i = 0; -// for (ExtrusionEntity *extr : collection.entities) { -// find_point(*extr, path + "[" + std::to_string(i) + "]"); -// i++; -// } -// } - -// static void find_point(ExtrusionEntity &extr, const std::string &path_info) { -// const ExtrusionPathSloped *sloped = dynamic_cast(&extr); -// if (sloped != nullptr) { -// throw RuntimeError("ExtrusionPathSloped not implemented"); -// return; -// } - -// ExtrusionPath *path = dynamic_cast(&extr); -// if (path != nullptr) { -// find_point(*path, path_info + " as ExtrusionPath " + ExtrusionEntity::role_to_string(extr.role())); -// return; -// } - -// ExtrusionLoop *loop = dynamic_cast(&extr); -// if (loop != nullptr) { -// find_point(*loop, path_info + " as ExtrusionLoop " + ExtrusionEntity::role_to_string(extr.role())); -// return; -// } - -// const ExtrusionLoopSloped *loop_sloped = dynamic_cast(&extr); -// if (loop_sloped != nullptr) { -// throw RuntimeError("ExtrusionLoopSloped not implemented"); -// return; -// } - -// ExtrusionEntityCollection *collection = dynamic_cast(&extr); -// if (collection != nullptr) { -// find_point(*collection, path_info + " as ExtrusionEntityCollection " + ExtrusionEntity::role_to_string(extr.role())); -// return; -// } - -// throw RuntimeError("ContourZ: ExtrusionEntity type not implemented"); -// return; -// } - void Layer::make_contour_z(const sla::IndexedMesh &mesh) { - // printf("make_contour_z() called\n"); for (LayerRegion *region : this->regions()) { - // printf("processing layer region %p\n", region); - // find_point(region->fills, "fills"); - // find_point(region->perimeters, "perimeters"); - handle_extrusion_collection(region, mesh, region->fills, {erTopSolidInfill, erIroning, erExternalPerimeter, erMixed}); handle_extrusion_collection(region, mesh, region->perimeters, {erExternalPerimeter, erMixed}); } } -} // namespace Slic3r \ No newline at end of file +} // namespace Slic3r diff --git a/version.inc b/version.inc index 86d3759e73..d6c6b293b3 100644 --- a/version.inc +++ b/version.inc @@ -8,7 +8,6 @@ if(NOT DEFINED BBL_INTERNAL_TESTING) set(BBL_INTERNAL_TESTING "0") endif() set(SoftFever_VERSION "2.3.2-dev") -set(ZAA_VERSION "1.0.3") string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" SoftFever_VERSION_MATCH ${SoftFever_VERSION}) set(ORCA_VERSION_MAJOR ${CMAKE_MATCH_1})