Skip to content

Migrate Replicad to OCCT v8 bindings#263

Draft
rifont wants to merge 37 commits into
sgenoud:mainfrom
taucad:main
Draft

Migrate Replicad to OCCT v8 bindings#263
rifont wants to merge 37 commits into
sgenoud:mainfrom
taucad:main

Conversation

@rifont

@rifont rifont commented Jun 14, 2026

Copy link
Copy Markdown

Summary

  • Migrates Replicad's OpenCascade.js bindings and TypeScript wrapper usage to the OCCT v8 API surface.
  • Adds generated single-threaded and multi-threaded WASM builds under packages/replicad-opencascadejs/dist, with package exports for the default single build and the ./multi subpath.
  • Updates Replicad shape, curve, projection, mesh extraction, STEP export, tests, studio, CLI, evaluator, and app-example consumers for the new package exports and OCCT constructor/method names.
  • Adds a small app-example Vite worker config fix so the ESM OCJS worker build can code-split successfully.

Reviewer notes

  • Opened as a draft from the existing taucad:main branch as requested, preserving the current commit stack rather than squashing or creating a new PR branch.
  • The package metadata currently uses the Tau fork package names (@taucad/replicad, @taucad/replicad-opencascadejs) and Tau repository URLs. This likely needs maintainer discussion before the PR is marked ready for upstream.
  • docs/occt-v8-migration.md still says the multi-threaded build was removed/deferred, but this branch adds replicad_multi.* artifacts and ./multi exports. That doc should be reconciled before final review.
  • The generated WASM/type/symbol artifacts dominate the diff; source review should focus first on packages/replicad/src, packages/replicad-opencascadejs/build-source, and the package export/import changes.

Test plan

  • pnpm install --frozen-lockfile
  • pnpm --filter @taucad/replicad typecheck
  • pnpm --filter @taucad/replicad test -- --run (4 files, 39 tests)
  • pnpm --filter @taucad/replicad build
  • pnpm --filter replicad-cli build
  • pnpm --filter replicad-evaluator build
  • pnpm --filter studio build (passed with existing dependency/CSS/chunk-size warnings)
  • pnpm --filter replicad-app-example build (initially failed on worker IIFE/code-splitting, fixed by building workers as ES modules)
  • Node smoke: default replicad-opencascadejs export initializes and exposes BRepPrimAPI_MakeBox plus exception helpers
  • Node smoke: replicad-opencascadejs/multi export initializes and exposes BRepPrimAPI_MakeBox plus exception helpers
  • Node smoke: built dist/replicad.js initializes OCJS and meshes a simple box
  • npm pack --dry-run --json in packages/replicad-opencascadejs
  • npm pack --dry-run --json in packages/replicad

Risks

  • High review surface area: this is a large generated-artifact and API migration PR rather than a small feature patch.
  • Package identity and publication semantics need upstream maintainer confirmation because the current branch is configured for Tau-scoped beta packages.
  • Browser builds pass, but studio/app-example still emit warnings for dependency externals, duplicate WASM emission, large chunks, and old Browserslist data.
  • Docker rebuild of the OCJS WASM artifacts was not rerun during this PR prep; validation used the committed generated artifacts.

AI Disclosure

  • AI assistance used: yes
  • Model: GPT-5 Codex
  • Scope of AI assistance: diff review, validation, one app-example build fix, and PR drafting
  • Human verification: draft PR opened for human maintainer review; local validation commands above were run before submission

rifont added 30 commits March 7, 2026 11:24
Rebuilt both WASM variants against OCCT V8 with -O3 optimization:
- replicad_single: compact build without exception support (18.96 MB)
- replicad_with_exceptions: full build with native WASM exceptions (22.22 MB)

Also includes replicad source updates for OCCT V8 API compatibility.

Made-with: Cursor
orts and add multi-threaded build
rifont and others added 7 commits May 31, 2026 16:51
Reconciles upstream v0.21.1..v0.23.3 (mesh shape import/export, replicad
evaluator + node CLI, sketch.revolve angle param, draft angle, projection
approximation fixes, isShape3D chaining) with taucad fork customizations
(OCCT V8 dual-WASM binding, suffix-free OCJS symbols, ESM sub-path exports,
PBR/material density export, native C++ mesh extractors).

Conflict resolutions:
- packages/replicad/package.json: keep @taucad/replicad name + version
  0.23.3-beta.0; replicad-opencascadejs stays a workspace dependency
  (not the upstream ^0.23.0 devDep).
- packages/replicad-opencascadejs/*: keep fork dist/-based packaging,
  single+multi build configs; honor fork deletion of src/*.wasm/*.d.ts
  and custom_build_with_exceptions.yml.
- src/lib2d/approximations.ts: adopt upstream bounded BSpline->Bezier
  conversion (handle, U1, U2, tol) via the fork's suffix-free
  Geom2dConvert_BSplineCurveToBezierCurve symbol.
- src/shapes.ts: union of imports (asDir/makePln/makePlane/BRepAdaptor_Surface)
  in fork style.
- src/sketches/CompoundSketch.ts: adopt upstream revolve() angle parameter.
- peripheral packages (studio, replicad-app-example, pnpm-lock): keep fork.

Co-authored-by: Cursor <cursoragent@cursor.com>

@sgenoud sgenoud left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!

I know this is still just a draft, but I wanted to have a look to guide your next step!

Thanks for the work


// We import our model as a simple function
import { drawBox } from "./cad";
import { drawBox } from './cad';

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure you run prettier (with default config) to keep the same quotes than before.

"replicad-opencascadejs": "^0.23.0",
"replicad-threejs-helper": "^0.23.0",
"replicad": "^0.21.0",
"replicad-opencascadejs": "workspace:@taucad/replicad-opencascadejs@^",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to change

// same tolerance/angularTolerance budget as the face mesher.
//
// `seenEdges` deduplicates edges shared between adjacent faces so a single
// shared edge contributes exactly one polyline.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way this could be maintained in another repo?

bindings: #@ data.values.bindings
emccFlags: #@ data.values.buildFlags

additionalCppFiles:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like that this is in files instead of inline. This could help making it more maintainable as well!

- -msimd128
- -O3

# Legacy inline C++ kept for reference; wrapper .cpp files in build-config/wrappers/ are used instead.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The git history is here for reference, we can remove this entirely.


return handle as T;
};

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to build this helper?


if (curveType === "BEZIER_CURVE") {
const b = adaptor.Bezier().get();
const b = adaptor.Bezier();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain me how the dynamic pointers have changed with v8? We might need to do some additional memory management (with the previous way when a resource was using one of these it would be freed automatically I think).

@@ -477,110 +433,34 @@ export class Shape<Type extends TopoDS_Shape> extends WrappingObj<Type> {
lines: number[];
edgeGroups: { start: number; count: number; edgeId: number }[];
} {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we keep the js implementation as a fallback (in case we run in with a wasm that does not have the cpp implementation?)

"version": "0.23.1",
"description": "The library to build browser based 3D models with code",
"name": "@taucad/replicad",
"version": "0.23.3-beta.1",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leftover

if (manifold?.Manifold) {
manifold.setup();
replicad.setManifold(manifold);
export function runInContextAsOC(code, context = {}) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be some rebase issue here, I have modified how this works in the mean time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants