DotNetCore.OCCTProxy
1.0.5
dotnet add package DotNetCore.OCCTProxy --version 1.0.5
NuGet\Install-Package DotNetCore.OCCTProxy -Version 1.0.5
<PackageReference Include="DotNetCore.OCCTProxy" Version="1.0.5" />
<PackageVersion Include="DotNetCore.OCCTProxy" Version="1.0.5" />
<PackageReference Include="DotNetCore.OCCTProxy" />
paket add DotNetCore.OCCTProxy --version 1.0.5
#r "nuget: DotNetCore.OCCTProxy, 1.0.5"
#:package DotNetCore.OCCTProxy@1.0.5
#addin nuget:?package=DotNetCore.OCCTProxy&version=1.0.5
#tool nuget:?package=DotNetCore.OCCTProxy&version=1.0.5
OCCTProxy NuGet Package
概述
OCCTProxy 是一个 C++/CLI 包装器,用于在 .NET 8 应用程序中使用 OpenCASCADE 7.9.3。
平台支持: 此包仅适用于 Windows x64 平台,不支持 Linux、macOS 或 ARM 架构。
功能:
- STEP 文件导入并转换为 GLB
- IGES 文件导入并转换为 GLB
- 自动格式检测
- 网格质量控制
- 进度回调
- 坐标系转换(Z-up → Y-up)
包含内容:
OCCTProxy.dll- C++/CLI 托管程序集- 41 个原生 DLL(OpenCASCADE + 第三方依赖)
- 约 70MB 总大小
安装
从本地源安装
# 添加本地 NuGet 源
dotnet nuget add source "C:\path\to\NuGet" -n OCCTProxyLocal
# 安装包
dotnet add package DotNetCore.OCCTProxy
项目配置
在 .csproj 文件中确保以下配置:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.OCCTProxy" Version="1.0.5" />
</ItemGroup>
</Project>
重要:
PlatformTarget必须设置为x64,OCCTProxy 仅支持 64 位TargetFramework设置为net8.0,此包仅在 Windows 平台上运行
快速开始
1. 添加 DLL 初始化辅助类
在使用 OCCTProxy 之前,必须设置原生 DLL 搜索路径。请将以下辅助类添加到您的项目中:
using System.Runtime.InteropServices;
/// <summary>
/// OpenCASCADE 环境初始化辅助类
/// 请将此类添加到您的项目中
/// </summary>
public static class OcctEnvironment
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName);
private static bool _initialized;
/// <summary>
/// 初始化 OpenCASCADE 运行环境
/// 必须在使用 CadConverter 之前调用一次
/// </summary>
public static void Initialize()
{
if (_initialized) return;
var baseDir = AppContext.BaseDirectory;
var occtPath = Path.Combine(baseDir, "OpenCascade", "x64");
if (Directory.Exists(occtPath) && OperatingSystem.IsWindows())
{
SetDllDirectory(occtPath);
_initialized = true;
}
else
{
throw new DirectoryNotFoundException(
$"OpenCASCADE DLL 目录不存在: {occtPath}");
}
}
}
说明:
OcctEnvironment不是 OCCTProxy NuGet 包的一部分,您需要将上述代码复制到项目中。
2. 基本用法
using OCCTProxyLib;
// 初始化环境(程序启动时调用一次)
OcctEnvironment.Initialize();
// 使用 using 语句确保资源释放
using (var converter = new CadConverter())
{
// STEP → GLB
var result = converter.ConvertStepToGlb(
"input.step",
"output.glb",
MeshQuality.Standard,
null); // 无进度回调
if (result.Success)
{
Console.WriteLine($"转换成功:");
Console.WriteLine($" 形状数: {result.ShapeCount}");
Console.WriteLine($" 面数: {result.FaceCount}");
Console.WriteLine($" 三角形数: {result.TriangleCount}");
}
else
{
Console.WriteLine($"转换失败: {result.ErrorMessage}");
}
}
API 参考
CadConverter 类
主要的转换器类,实现了 IDisposable 接口。
public ref class CadConverter : IDisposable
{
// 构造函数
CadConverter();
// STEP → GLB
ConvertResult ConvertStepToGlb(
string inputPath,
string outputPath,
MeshQuality quality,
ProgressCallback progress);
ConvertResult ConvertStepToGlb(
string inputPath,
string outputPath,
MeshParams meshParams,
GlbExportParams exportParams,
ProgressCallback progress);
// IGES → GLB
ConvertResult ConvertIgesToGlb(
string inputPath,
string outputPath,
MeshQuality quality,
ProgressCallback progress);
ConvertResult ConvertIgesToGlb(
string inputPath,
string outputPath,
MeshParams meshParams,
GlbExportParams exportParams,
ProgressCallback progress);
// 自动检测格式
ConvertResult ConvertToGlb(
string inputPath,
string outputPath,
MeshQuality quality,
ProgressCallback progress);
// OpenCASCADE 版本
static string OcctVersion { get; }
}
MeshQuality 枚举
public enum MeshQuality
{
Low, // 低精度,文件小
Standard, // 标准精度(推荐)
High // 高精度,文件大
}
MeshParams 类
自定义网格化参数:
public ref class MeshParams
{
double LinearDeflection; // 线性偏差,默认 0.1
double AngularDeflection; // 角度偏差(弧度),默认 0.5
bool IsRelative; // 是否使用相对偏差,默认 false
bool IsParallel; // 是否并行计算,默认 true
// 从质量级别创建
static MeshParams FromQuality(MeshQuality quality);
}
GlbExportParams 类
GLB 导出参数:
public ref class GlbExportParams
{
CoordinateSystem OutputCoordinateSystem; // 输出坐标系,默认 Y-up
bool EmbedTextures; // 是否嵌入纹理,默认 true
bool MergeFaces; // 是否合并面,默认 false
bool ForcedUVExport; // 是否强制导出 UV,默认 false
}
CoordinateSystem 枚举
public enum CoordinateSystem
{
Undefined = 0,
Zup = 1, // Z 轴向上(CAD 标准)
Yup = 2 // Y 轴向上(glTF 标准)
}
ConvertResult 类
转换结果:
public ref class ConvertResult
{
bool Success; // 是否成功
string ErrorMessage; // 错误信息
int ShapeCount; // 形状数量
int FaceCount; // 面数量
int TriangleCount; // 三角形数量
}
ProgressCallback 委托
public delegate void ProgressCallback(int percent, string stage);
完整示例
示例 0:控制台应用程序(最简示例)
using System.Runtime.InteropServices;
using OCCTProxyLib;
// 初始化 DLL 路径
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern bool SetDllDirectory(string path);
var occtPath = Path.Combine(AppContext.BaseDirectory, "OpenCascade", "x64");
SetDllDirectory(occtPath);
// 显示 OpenCASCADE 版本
Console.WriteLine($"OpenCASCADE Version: {CadConverter.OcctVersion}");
// 转换 STEP 到 GLB
using var converter = new CadConverter();
var result = converter.ConvertToGlb(
args[0], // 输入文件
Path.ChangeExtension(args[0], ".glb"),
MeshQuality.Standard,
null);
Console.WriteLine(result.Success
? $"成功: {result.TriangleCount} 三角形"
: $"失败: {result.ErrorMessage}");
示例 1:带进度回调的转换
using OCCTProxyLib;
OcctEnvironment.Initialize();
using var converter = new CadConverter();
// 定义进度回调
ProgressCallback progress = (percent, stage) =>
{
Console.WriteLine($"[{percent,3}%] {stage}");
};
var result = converter.ConvertStepToGlb(
@"C:\Models\assembly.step",
@"C:\Output\assembly.glb",
MeshQuality.High,
progress);
if (result.Success)
{
Console.WriteLine($"\n转换完成!");
Console.WriteLine($"三角形数: {result.TriangleCount:N0}");
}
示例 2:自定义参数转换
using OCCTProxyLib;
OcctEnvironment.Initialize();
using var converter = new CadConverter();
// 自定义网格参数
var meshParams = new MeshParams
{
LinearDeflection = 0.05, // 更高精度
AngularDeflection = 0.2,
IsParallel = true
};
// 自定义导出参数
var exportParams = new GlbExportParams
{
OutputCoordinateSystem = CoordinateSystem.Yup,
MergeFaces = true
};
var result = converter.ConvertStepToGlb(
"input.step",
"output.glb",
meshParams,
exportParams,
null);
示例 3:批量转换
using OCCTProxyLib;
public class BatchConverter : IDisposable
{
private readonly CadConverter _converter;
public BatchConverter()
{
OcctEnvironment.Initialize();
_converter = new CadConverter();
}
public void ConvertAll(string inputDir, string outputDir)
{
var files = Directory.GetFiles(inputDir, "*.step")
.Concat(Directory.GetFiles(inputDir, "*.stp"))
.Concat(Directory.GetFiles(inputDir, "*.iges"))
.Concat(Directory.GetFiles(inputDir, "*.igs"));
foreach (var file in files)
{
var outputFile = Path.Combine(
outputDir,
Path.GetFileNameWithoutExtension(file) + ".glb");
Console.WriteLine($"转换: {Path.GetFileName(file)}");
var result = _converter.ConvertToGlb(
file, outputFile, MeshQuality.Standard, null);
if (!result.Success)
{
Console.WriteLine($" 失败: {result.ErrorMessage}");
}
}
}
public void Dispose()
{
_converter?.Dispose();
}
}
// 使用
using var batch = new BatchConverter();
batch.ConvertAll(@"C:\CAD\Input", @"C:\CAD\Output");
示例 4:ASP.NET Core Web API
using Microsoft.AspNetCore.Mvc;
using OCCTProxyLib;
[ApiController]
[Route("api/[controller]")]
public class CadConverterController : ControllerBase
{
static CadConverterController()
{
// 应用启动时初始化一次
OcctEnvironment.Initialize();
}
[HttpPost("convert")]
public async Task<IActionResult> Convert(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("请上传文件");
var ext = Path.GetExtension(file.FileName).ToLower();
if (ext != ".step" && ext != ".stp" && ext != ".iges" && ext != ".igs")
return BadRequest("仅支持 STEP 和 IGES 格式");
var tempInput = Path.GetTempFileName() + ext;
var tempOutput = Path.ChangeExtension(tempInput, ".glb");
try
{
// 保存上传文件
using (var stream = System.IO.File.Create(tempInput))
{
await file.CopyToAsync(stream);
}
// 转换(每次请求创建新实例以支持并发)
using var converter = new CadConverter();
var result = converter.ConvertToGlb(
tempInput, tempOutput, MeshQuality.Standard, null);
if (!result.Success)
return BadRequest($"转换失败: {result.ErrorMessage}");
// 返回 GLB 文件
var bytes = await System.IO.File.ReadAllBytesAsync(tempOutput);
return File(bytes, "model/gltf-binary",
Path.GetFileNameWithoutExtension(file.FileName) + ".glb");
}
finally
{
// 清理临时文件
if (System.IO.File.Exists(tempInput))
System.IO.File.Delete(tempInput);
if (System.IO.File.Exists(tempOutput))
System.IO.File.Delete(tempOutput);
}
}
}
资源释放最佳实践
1. 使用 using 语句(推荐)
using (var converter = new CadConverter())
{
// 使用 converter
} // 自动调用 Dispose()
2. 使用 using 声明(C# 8.0+)
using var converter = new CadConverter();
// 使用 converter
// 方法结束时自动释放
3. 手动释放
var converter = new CadConverter();
try
{
// 使用 converter
}
finally
{
converter.Dispose();
}
4. 长生命周期服务
public class CadService : IDisposable
{
private readonly CadConverter _converter;
private bool _disposed;
public CadService()
{
OcctEnvironment.Initialize();
_converter = new CadConverter();
}
public ConvertResult Convert(string input, string output)
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _converter.ConvertToGlb(input, output, MeshQuality.Standard, null);
}
public void Dispose()
{
if (_disposed) return;
_converter?.Dispose();
_disposed = true;
}
}
注意事项
线程安全:
CadConverter不是线程安全的。多线程场景下,每个线程应使用独立的实例。内存占用: 大型 CAD 文件可能消耗大量内存。建议:
- 使用完立即释放
- 避免同时加载多个大文件
DLL 路径: 必须在使用
CadConverter前调用OcctEnvironment.Initialize()。文件编码: STEP/IGES 文件路径支持 Unicode。
坐标系: CAD 文件通常使用 Z-up,glTF 标准使用 Y-up,默认自动转换。
系统要求
- 操作系统: Windows 7 SP1+ / Windows 10 / Windows 11 x64(仅支持 Windows 平台)
- .NET 运行时: .NET 8.0 或更高版本
- Visual C++ 运行时: Visual C++ Redistributable 2015-2022(已包含在包中)
- 平台限制: 此包仅适用于 Windows x64 系统,不支持 Linux、macOS 或 ARM 架构
关于 Ijwhost.dll
OCCTProxy 是 C++/CLI 混合模式程序集,在 .NET Core/.NET 5+ 环境中需要 Ijwhost.dll 来加载。
重要说明:
自动提供的情况(推荐)
当满足以下条件时,Ijwhost.dll 由 .NET 运行时自动提供:
- 使用
.NET Desktop Runtime(Microsoft.NET.Sdk.WindowsDesktop或UseWPF/UseWindowsForms) - 已安装 .NET 8.0 Desktop Runtime
- 运行时会自动从以下位置加载:
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Host.win-x64\<version>\runtimes\win-x64\native\
需要手动复制的情况
当使用 Microsoft.NET.Sdk (非 Desktop 项目) 时,Ijwhost.dll 不会自动由运行时提供。
好消息:本 NuGet 包会自动处理!
NuGet 包会在构建时从以下位置动态查找并复制与您当前 SDK 版本匹配的 Ijwhost.dll:
- NuGet 缓存:
$(NuGetPackageRoot)microsoft.netcore.app.host.win-x64\<版本>\runtimes\win-x64\native\ - 全局 dotnet packs:
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Host.win-x64\<版本>\runtimes\win-x64\native\
这确保了 Ijwhost.dll 始终与您的 .NET SDK 版本兼容,无需手动干预。
使用示例:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.OCCTProxy" Version="1.0.4" />
</ItemGroup>
</Project>
如果需要手动复制(仅在极少数情况下):
<ItemGroup>
<None Include="Ijwhost.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
独立部署:如果使用 dotnet publish --self-contained,Ijwhost.dll 会自动包含在发布目录中。
常见错误
如果遇到以下错误:
Could not load file or assembly 'OCCTProxy.dll'. 找不到指定的模块。
通常是因为缺少 Ijwhost.dll。解决方案:
- 确保已安装 .NET 8.0 Desktop Runtime
- 或使用上述方式手动复制
Ijwhost.dll - 确认应用程序以 x64 模式运行
Windows 版本兼容性
| Windows 版本 | 支持状态 | 备注 |
|---|---|---|
| Windows 11 x64 | ✅ 完全支持 | |
| Windows 10 x64 | ✅ 完全支持 | |
| Windows 8.1 x64 | ✅ 支持 | 需安装 KB2999226 |
| Windows 7 SP1 x64 | ✅ 支持 | 需安装 KB2533623, KB2999226 |
| ARM64 | ❌ 不支持 | 仅 x64 |
Windows 7 SP1 运行要求
在 Windows 7 SP1 上运行 .NET 8 应用程序,需要安装以下更新:
- KB2533623 - 扩展保护机制更新
- KB2999226 - Universal C Runtime (必需)
- KB3063858 - 安全更新(推荐)
注意: 虽然 .NET 8 可以在 Windows 7 SP1 上运行,但微软官方不提供技术支持。
故障排除
"找不到指定的模块" 错误
Could not load file or assembly 'OCCTProxy.dll'. 找不到指定的模块。
解决方案: 确保在使用前调用 OcctEnvironment.Initialize()。
转换失败
检查 ConvertResult.ErrorMessage 获取详细错误信息。常见原因:
- 文件格式不正确
- 文件损坏
- 内存不足
输出文件很大
使用 MeshQuality.Low 或调整 MeshParams.LinearDeflection 降低精度。
许可证
- OCCTProxy: MIT License
- OpenCASCADE: LGPL 2.1
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
- v1.0.5: 网格化阶段 shape 级并行优化(OSD_Parallel::For),多顶层 shape 并行网格化
- v1.0.4: 修复中文路径支持(UTF-8 编码)
- v1.0.3: Ijwhost.dll 从用户 SDK Runtime 动态复制,确保版本兼容
- 支持 STEP/IGES 导入
- 支持 glTF/GLB 导出
- 基于 OpenCASCADE 7.9.3