OpenSKP

The open-source SketchUp (.skp) file parser โ€” Dart / Flutter edition.

Parse .skp files without SketchUp. No SDK. No license. Just code.

Pub Version License: MIT

๐Ÿ  openskp.com ยท ๐ŸŒ Try the Live Web Viewer ยท ๐Ÿ“– Docs ยท Changelog

Important

This project was built by reverse engineering a proprietary binary format. It is not affiliated with or endorsed by Trimble Inc. or SketchUp.


๐ŸŒŸ What is OpenSKP?

OpenSKP is the first and only open-source, cross-platform parser for SketchUp binary files โ€” reverse-engineered from both the modern VFF container (SketchUp 2021+) and the classic MFC CArchive container (SketchUp 2013โ€“2020). It gives Dart and Flutter developers full programmatic access to geometry, materials, components, layers, and metadata, with no SketchUp installation and no proprietary SDK required. The same parser and export API also ship as first-class packages for Python, TypeScript, .NET, and C++ โ€” see the project README for the full cross-language picture.

This package can also write new .skp files from scratch, and edit existing ones, validated feature-by-feature against the real SketchUp SDK (see Writing below).


๐ŸŒŸ Vision & Platform Coverage

Enable mobile (iOS/Android), desktop, and web developers to parse and build 3D SketchUp file viewer pipelines natively inside Flutter.

  • Mobile: Flutter iOS & Android apps
  • Desktop: Flutter Windows, macOS, and Linux
  • Web: Compile client-side for browser-based parsers
  • Server: Dart shelf backend parsing services

๐ŸŒ Try the Live Web Viewer (Drag-and-Drop)


โœจ Features

  • Zero Native Dependencies: 100% pure Dart implementation.
  • Full-fidelity parsing: vertices, edges, faces, normals, UV coordinates, nested component hierarchies, layers/tags, materials, textures, styles, and dynamic-component attributes.
  • Both SketchUp file generations: modern VFF (2021+) and legacy MFC (2013โ€“2020) containers, transparently, behind one parse() call.
  • Scene baking: an opt-in buildScene() pass resolves the full placed scene graph to world-space, triangulated, export-ready geometry.
  • Native multi-format export: glTF (GLB), Wavefront OBJ/MTL, STL, PLY, AutoCAD DXF (3DFACE and Polyface Mesh), IFC4 (BIM/ISO 10303-21 STEP) โ€” all written from scratch, no third-party CAD/BIM SDK involved. The DXF writer is verified against real desktop AutoCAD, not just lenient DXF readers.
  • Write support: build new legacy-format .skp files from scratch: geometry (including true, editable circular/arc curves, freeform polylines, faces with holes cut out, and non-planar auto-triangulation), materials (solid + PNG/JPEG textures), layers, nested component definitions and groups, instance rotation/visibility, and custom attribute dictionaries โ€” or load and extend an existing file with openExisting(). No SDK involved; every feature validated against the real SketchUp SDK. See Writing below.

๐Ÿš€ Installation

Add the library to your Dart or Flutter project:

# For Dart projects
dart pub add openskp

# For Flutter projects
flutter pub add openskp

๐Ÿ’ป Quick Start

1. Parsing a SketchUp File

Open a .skp file, read the byte buffer, and load the data model:

import 'dart:io';
import 'package:openskp/openskp.dart';

void main() async {
  // Read SKP file bytes
  final file = File('my_model.skp');
  final bytes = await file.readAsBytes();

  // Load and parse SKP model
  final skpFile = SkpFile.fromBuffer(bytes);
  final model = skpFile.parse();

  print('SketchUp File Version: ${model.version}');

  // Inspect Layers
  print('Layers:');
  for (var layer in model.layers) {
    print('- ${layer.name} (RGB: ${layer.colorR}, ${layer.colorG}, ${layer.colorB})');
  }

  // Inspect Materials
  print('Materials:');
  for (var material in model.materials) {
    print('- ${material.name} (Opacity: ${material.transparency})');
  }

  // Walk component definitions and their geometry
  model.definitions.forEach((id, def) {
    print('Definition $id: ${def.name} - ${def.vertices.length} vertices, ${def.faces.length} faces');
  });

  // model.root holds whatever is placed directly in the model (not inside
  // any component/group), including root-level instances.
  print('Root-level instances: ${model.root.instances.length}');
}

2. Baking Scene Graph & GLB Export

Bake all placed instances into world-space, triangulated mesh primitives ready for 3D rendering or GLB export:

import 'dart:io';
import 'package:openskp/openskp.dart';

void main() async {
  final bytes = await File('my_model.skp').readAsBytes();
  final skpFile = SkpFile.fromBuffer(bytes);

  // Bake scene graph into world-space meshes
  final scene = skpFile.buildScene();

  print('Renderable primitives: ${scene.glbPrimitives.length}');
  for (var entry in scene.meshIndex.entries) {
    print('- Mesh ${entry.key}: ${entry.value.definitionName} [${entry.value.layer}]');
  }

  // Export to binary glTF 2.0 (GLB) bytes or file
  final glbBytes = toGlb(scene);
  await exportGlb(scene, 'my_model.glb');
  print('Exported GLB: ${glbBytes.length} bytes');

  // Export to Wavefront OBJ, plus a companion .mtl material library
  final objText = toObj(scene);
  final mtlText = toMtl(scene);
  exportObj(scene, 'my_model.obj'); // writes .obj + .mtl together

  // Export to STL (3D printing), ASCII or little-endian binary
  final stlBytes = toStlBinary(scene);
  exportStl(scene, 'my_model.stl', binary: true);

  // Export to PLY (Stanford Triangle Format), ASCII or little-endian binary
  final plyBytes = toPlyBinary(scene);
  exportPly(scene, 'my_model.ply', binary: true);

  // Export to 3D DXF (AutoCAD R2000 compliant, Polyface Mesh by default)
  final dxfText = toDxf(scene);
  exportDxf(scene, 'my_model.dxf');

  // Export to IFC4 / BIM (ISO 10303-21 STEP format)
  final ifcText = toIfc(scene);
  exportIfc(scene, 'my_model.ifc');
}

โœ๏ธ Writing

OpenSKP can also create new .skp files from scratch โ€” a genuine, from-scratch binary writer for the legacy MFC CArchive format (SketchUp 2013โ€“2020), with no SketchUp SDK involved at any point. Ports the same feature set as the Python package's writer, verified byte-identical to Python's own output on the same input: geometry, materials (solid + PNG/JPEG textures), layers (with color and default visibility), component definitions with multiple instances, groups, nested definitions and nested group instances, per-instance rotation and visibility, explicit per-side texture positioning, custom key/value attribute dictionaries, circular faces and partial arcs, freeform polyline curves, faces with holes cut out, and non-planar auto-triangulation. openExisting() loads an existing legacy-format file and rebuilds it as a new builder, so more geometry can be added before saving. See lib/src/create.dart for the full scope notes.

import 'package:openskp/openskp.dart';

void main() {
  final builder = create();

  // Materials and layers
  final red = builder.addMaterial('Red', [255, 0, 0]);
  final roof = builder.addLayer('Roof', color: [180, 60, 40]);

  // All addComponentDefinition/addGroup calls must come before any
  // addInstance/addFace call - placing anything locks in the file's
  // internal slot numbering for everything after it
  final chair = builder.addComponentDefinition('Chair', (def) {
    def.addFace([(0.0, 0.0, 0.0), (20.0, 0.0, 0.0), (20.0, 20.0, 0.0), (0.0, 20.0, 0.0)]);
  });
  builder.addInstance(chair, translation: (50.0, 0.0, 0.0));
  builder.addInstance(chair, translation: (100.0, 0.0, 0.0), hidden: true);

  builder.addFace(
    [(0.0, 0.0, 0.0), (100.0, 0.0, 0.0), (100.0, 100.0, 0.0), (0.0, 100.0, 0.0)],
    material: red, layer: roof,
  );

  builder.save('output.skp');
}

Editing an existing file

final result = openExisting('building.skp');
for (final w in result.warnings) print('not fully reproduced: $w');

result.builder.addCircle((0.0, 0.0, 100.0), (0.0, 0.0, 1.0), 50.0);
result.builder.save('building_edited.skp');

result.warnings is the honest account of what couldn't be faithfully reproduced from that specific source file. Every material/layer the source had is reachable on result.builder.materialsByName/ layersByName without a separate lookup, and result.definitions maps each replayed component definition's own name to its builder for placing more instances of something the source already defined.


๐Ÿ“ API Data Model Reference

The public API is designed to mirror the Python reference implementation's data model (the same shape the C# port also follows):

SkpModel

  • String version โ€” The parsed SketchUp application version.
  • String? units โ€” Model unit-system string (e.g., "Millimeter").
  • Map<int, Definition> definitions โ€” Component/group geometry definitions, keyed by their numeric TLV entity ID.
  • Definition root โ€” Whatever is placed directly in the model (not inside any component/group).
  • List<Layer> layers โ€” Layer names, colors, and hidden visibility flags.
  • List<Material> materials โ€” Material names, colors, transparency, and embedded textures.
  • Map<int, Material> materialsById โ€” Join table from a TLV material ID (Face.materialId) to its Material.
  • List<Style> styles โ€” Bundled rendering styles (default front/back face colors).

Scene & GLB Export

  • Scene buildScene() โ€” Opt-in scene graph flattener; resolves nested instance transforms into world-space meshes.
  • List<GlbPrimitive> glbPrimitives โ€” Triangulated mesh primitives ready for GPU upload or GLB packaging.
  • Map<String, MeshMetadata> meshIndex โ€” Metadata map describing each baked mesh primitive, keyed by the matching GlbPrimitive.geomName.
  • Uint8List toGlb(Scene scene) โ€” Serializes a baked scene into binary glTF 2.0 (GLB) bytes.
  • Future<File> exportGlb(Scene scene, String path) โ€” Exports a baked scene directly to a .glb file on disk.

๐Ÿญ Used in Production

OpenSKP powers the SketchUp import pipeline for FrameSmart (a 3D collaboration platform with nearly 200 active users) and IngeTrazo (a SketchUp-alternative 3D modeler with a BIM โ†’ IFC bridge). Using OpenSKP in your own project? Open an issue or a PR to get added here.


๐Ÿ“„ License

This library is open-source software licensed under the MIT License โ€” see the LICENSE file for details.

Libraries

openskp
A pure Dart implementation of the OpenSKP parser: extracts geometry, metadata, layers, and materials from SketchUp (.skp) binary files.