支持批处理目录
This commit is contained in:
parent
20ce7caaa8
commit
939a56ae03
@ -10,9 +10,10 @@
|
||||
"mcp__serena__write_memory",
|
||||
"mcp__serena__search_for_pattern",
|
||||
"mcp__context7__resolve-library-id",
|
||||
"mcp__context7__get-library-docs"
|
||||
"mcp__context7__get-library-docs",
|
||||
"Bash(wc -l:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
87
README.md
87
README.md
@ -1,3 +1,90 @@
|
||||
Win11 打包流程(生成适用于 Win7 的静态版)
|
||||
1. 进入 VS 2022 开发者命令行
|
||||
打开“x64 Native Tools Command Prompt for VS 2022”(或在 PowerShell 中执行 cmd.exe /k
|
||||
"<VS路径>\vcvars64.bat" 并在新开的 CMD 中操作)。
|
||||
|
||||
2. 安装/更新 Pixi 静态环境依赖
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe install -e static
|
||||
```
|
||||
|
||||
3. 清理旧的构建目录(可选但推荐)
|
||||
```bat
|
||||
rmdir /s /q build\win-static
|
||||
```
|
||||
|
||||
4. 配置静态工程(目标 Win7)
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake ^
|
||||
-G "Visual Studio 17 2022" -A x64 ^
|
||||
-S . -B build\win-static ^
|
||||
-DWIN32_WINNT=0x0601 ^
|
||||
-DBUILD_STATIC=ON -DBUILD_SHARED_LIBS=OFF ^
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
```
|
||||
|
||||
5. 编译 Release 可执行文件
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake --build build\win-static --config Release
|
||||
```
|
||||
|
||||
6. (可选)安装到 Pixi 环境 bin
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake --install build\win-static --config Release
|
||||
```
|
||||
|
||||
7. 产物位置
|
||||
• 未安装:build\win-static\Release\STP2GLB.exe
|
||||
• 安装后:.pixi\envs\static\Library\bin\STP2GLB.exe
|
||||
|
||||
──────────────────────────────────────────
|
||||
|
||||
Win7 打包流程(直接在 Win7 上构建)
|
||||
|
||||
前提:Win7 SP1 + VS 2019/2022(带 MSVC v142/v143),安装 Pixi,并确保 SDK/工具链支持 VS 构建。
|
||||
|
||||
1. 使用已配置好的 VS 开发者命令行
|
||||
启动 Win7 上的 “x64 Native Tools Command Prompt”,保证 cl.exe 和 cmake 可用。
|
||||
|
||||
2. 安装 Pixi 静态环境依赖
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe install -e static
|
||||
```
|
||||
|
||||
3. 清理旧目录
|
||||
```bat
|
||||
rmdir /s /q build\win-static
|
||||
```
|
||||
|
||||
4. 配置工程(同样指定 Win7)
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake ^
|
||||
-G "Visual Studio 17 2022" -A x64 ^
|
||||
-S . -B build\win-static ^
|
||||
-DWIN32_WINNT=0x0601 ^
|
||||
-DBUILD_STATIC=ON -DBUILD_SHARED_LIBS=OFF ^
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
```
|
||||
|
||||
5. 编译 Release
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake --build build\win-static --config Release
|
||||
```
|
||||
|
||||
6. (可选)安装
|
||||
```bat
|
||||
C:\Users\sladr\.pixi\bin\pixi.exe run -e static cmake --install build\win-static --config Release
|
||||
```
|
||||
|
||||
7. 产物位置
|
||||
同 Win11 流程,产物可执行文件位于构建目录或安装后的 Pixi 环境 bin 目录。
|
||||
|
||||
──────────────────────────────────────────
|
||||
|
||||
注意事项
|
||||
• 每次变更代码后建议在 Win11 构建并将 STP2GLB.exe 拷贝到 Win7 实机进行实际验证。
|
||||
• 若在 Win7 上本地构建,需确保 VS 工具链与 Windows SDK 在该机器上完整可用;否则可在 Win11
|
||||
构建后直接拷贝二进制。
|
||||
# Stp2Glb
|
||||
|
||||
## Usage
|
||||
|
||||
BIN
STP2GLB.exe
BIN
STP2GLB.exe
Binary file not shown.
BIN
__pycache__/main.cpython-311.pyc
Normal file
BIN
__pycache__/main.cpython-311.pyc
Normal file
Binary file not shown.
@ -1,4 +1,7 @@
|
||||
# Find CGAL
|
||||
if(NOT CGAL_DIR)
|
||||
#set(CGAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/static/Library/cmake/CGAL" CACHE PATH "Path to CGAL installation")
|
||||
endif()
|
||||
find_package(CGAL REQUIRED)
|
||||
|
||||
if (CGAL_FOUND)
|
||||
|
||||
BIN
dragon_drc.glb
BIN
dragon_drc.glb
Binary file not shown.
BIN
gltfpack.exe
Normal file
BIN
gltfpack.exe
Normal file
Binary file not shown.
2
main.py
2
main.py
@ -264,4 +264,4 @@ def main():
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
||||
2
output5-log.json
Normal file
2
output5-log.json
Normal file
@ -0,0 +1,2 @@
|
||||
[
|
||||
]
|
||||
2
output6-log.json
Normal file
2
output6-log.json
Normal file
@ -0,0 +1,2 @@
|
||||
[
|
||||
]
|
||||
@ -56,6 +56,7 @@ cmake = "==3.30.5"
|
||||
cli11 = "*"
|
||||
ninja = "*"
|
||||
nlohmann_json = "*"
|
||||
cgal-cpp = "==5.6.1"
|
||||
|
||||
[feature.static.target.linux-64.dependencies]
|
||||
c-compiler = "*"
|
||||
@ -109,10 +110,13 @@ install = { cmd = ["ninja", "-C", "build/linux-static", "install"], description
|
||||
build = { cmd=["cmake","-G","Ninja", "--preset", "win-static-mingw", "--fresh"] }
|
||||
install = { cmd = ["ninja", "-C", "build/win-static-mingw", "install"], description = "Install the project" }
|
||||
|
||||
[dependencies]
|
||||
cgal-cpp = "==5.6.1"
|
||||
|
||||
[feature.conda.target.win-64.tasks]
|
||||
build-occt = { cmd=["rattler-build", "build", "-r", "recipes/occt-static/recipe.yaml", "-m","recipes/occt-static/conda_build_config-win.yaml"] }
|
||||
build-stepcode = { cmd=["rattler-build", "build", "-r", "recipes/stepcode-static/recipe.yaml", "-m","recipes/stepcode-static/conda_build_config-win.yaml"] }
|
||||
|
||||
[feature.conda.target.linux-64.tasks]
|
||||
build-occt = { cmd=["rattler-build", "build", "-r", "recipes/occt-static/recipe.yaml", "-m","recipes/occt-static/conda_build_config-linux.yaml"] }
|
||||
build-stepcode = { cmd=["rattler-build", "build", "-r", "recipes/stepcode-static/recipe.yaml", "-m","recipes/stepcode-static/conda_build_config-linux.yaml"] }
|
||||
build-stepcode = { cmd=["rattler-build", "build", "-r", "recipes/stepcode-static/recipe.yaml", "-m","recipes/stepcode-static/conda_build_config-linux.yaml"] }
|
||||
|
||||
@ -67,8 +67,12 @@ bool endsWithCaseInsensitive(const std::string& str, const std::string& suffix)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Main processing function
|
||||
GlobalConfig process_parameters(CLI::App& app)
|
||||
namespace {
|
||||
|
||||
GlobalConfig process_parameters_internal(CLI::App& app,
|
||||
const std::filesystem::path* stp_override,
|
||||
const std::filesystem::path* glb_override,
|
||||
const std::filesystem::path* compressed_glb_override)
|
||||
{
|
||||
const auto filter_names_include_input = app.get_option("--filter-names-include")->as<std::string>();
|
||||
const auto filter_names_file_include = app.get_option("--filter-names-file-include")->as<std::string>();
|
||||
@ -85,8 +89,8 @@ GlobalConfig process_parameters(CLI::App& app)
|
||||
const auto filter_names_include = process_filter_names(filter_names_include_input, filter_names_file_include);
|
||||
const auto filter_names_exclude = process_filter_names(filter_names_exclude_input, filter_names_file_exclude);
|
||||
|
||||
std::string stpFilename = app.get_option("--stp")->results()[0];
|
||||
std::string glbFilename = app.get_option("--glb")->results()[0];
|
||||
std::string stpFilename = stp_override ? stp_override->string() : app.get_option("--stp")->results()[0];
|
||||
std::string glbFilename = glb_override ? glb_override->string() : app.get_option("--glb")->results()[0];
|
||||
|
||||
bool isDownloadedFromUrl = false;
|
||||
std::string originalUrl;
|
||||
@ -155,8 +159,30 @@ GlobalConfig process_parameters(CLI::App& app)
|
||||
.is_downloaded_from_url = isDownloadedFromUrl,
|
||||
.original_url = originalUrl,
|
||||
.compress_glb = compress_glb,
|
||||
.compressed_glb_path = compressed_glb_value.empty() ? std::filesystem::path{} : std::filesystem::path(compressed_glb_value),
|
||||
.compressed_glb_path = compressed_glb_override
|
||||
? *compressed_glb_override
|
||||
: (compressed_glb_value.empty() ? std::filesystem::path{}
|
||||
: std::filesystem::path(compressed_glb_value)),
|
||||
.gltfpack_path = gltfpack_path_value,
|
||||
.gltfpack_args = gltfpack_args_value
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Main processing function
|
||||
GlobalConfig process_parameters(CLI::App& app)
|
||||
{
|
||||
return process_parameters_internal(app, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
GlobalConfig process_parameters(CLI::App& app,
|
||||
const std::filesystem::path& stp_path_override,
|
||||
const std::filesystem::path& glb_path_override,
|
||||
const std::filesystem::path& compressed_glb_path_override)
|
||||
{
|
||||
const std::filesystem::path* compressed_override_ptr = compressed_glb_path_override.empty()
|
||||
? nullptr
|
||||
: &compressed_glb_path_override;
|
||||
return process_parameters_internal(app, &stp_path_override, &glb_path_override, compressed_override_ptr);
|
||||
}
|
||||
|
||||
@ -4,12 +4,17 @@
|
||||
|
||||
#ifndef CONFIG_UTILS_H
|
||||
#define CONFIG_UTILS_H
|
||||
#include <filesystem>
|
||||
#include <CLI/App.hpp>
|
||||
|
||||
#include "config_structs.h"
|
||||
|
||||
|
||||
GlobalConfig process_parameters(CLI::App& app);
|
||||
GlobalConfig process_parameters(CLI::App& app,
|
||||
const std::filesystem::path& stp_path_override,
|
||||
const std::filesystem::path& glb_path_override,
|
||||
const std::filesystem::path& compressed_glb_path_override = {});
|
||||
|
||||
|
||||
#endif //CONFIG_UTILS_H
|
||||
|
||||
205
src/main.cpp
205
src/main.cpp
@ -5,7 +5,9 @@
|
||||
|
||||
#endif // Unix platform check
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "config_structs.h"
|
||||
#include <chrono>
|
||||
@ -17,6 +19,163 @@
|
||||
#include "http_server.h"
|
||||
#include "compression_utils.h"
|
||||
|
||||
void print_status(const GlobalConfig& config);
|
||||
|
||||
namespace {
|
||||
|
||||
bool is_step_file(const std::filesystem::path& path) {
|
||||
std::string extension = path.extension().string();
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char c) {
|
||||
return static_cast<char>(std::tolower(c));
|
||||
});
|
||||
return extension == ".stp" || extension == ".step";
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> collect_step_files(const std::filesystem::path& input_dir) {
|
||||
std::vector<std::filesystem::path> files;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(input_dir)) {
|
||||
if (entry.is_regular_file() && is_step_file(entry.path())) {
|
||||
files.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(files.begin(), files.end(), [](const auto& lhs, const auto& rhs) {
|
||||
return lhs.filename().string() < rhs.filename().string();
|
||||
});
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
int run_conversion(const GlobalConfig& config) {
|
||||
print_status(config);
|
||||
std::cout << "\n";
|
||||
std::cout << "Starting conversion..." << "\n";
|
||||
|
||||
const auto start = std::chrono::high_resolution_clock::now();
|
||||
try {
|
||||
if (config.buildConfig.build_bspline_surf)
|
||||
make_a_bspline_surf(config);
|
||||
|
||||
if (config.debug_mode == 1)
|
||||
debug_stp_to_glb(config);
|
||||
else
|
||||
convert_stp_to_glb(config);
|
||||
|
||||
apply_gltfpack_compression(config);
|
||||
} catch (std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto stop = std::chrono::high_resolution_clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
|
||||
const double seconds = static_cast<double>(duration.count()) / 1e6;
|
||||
std::cout << "STP converted in: " << std::fixed << std::setprecision(2) << seconds << " seconds" << "\n";
|
||||
|
||||
if (config.is_downloaded_from_url) {
|
||||
try {
|
||||
if (std::filesystem::exists(config.stpFile)) {
|
||||
std::filesystem::remove(config.stpFile);
|
||||
std::cout << "Cleaned up downloaded file: " << config.stpFile << "\n";
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "Warning: Failed to clean up downloaded file: " << ex.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_batch_conversion(CLI::App& app) {
|
||||
const std::filesystem::path input_dir = app.get_option("--stp")->results()[0];
|
||||
const std::filesystem::path output_dir = app.get_option("--glb")->results()[0];
|
||||
const auto step_files = collect_step_files(input_dir);
|
||||
|
||||
if (step_files.empty()) {
|
||||
std::cerr << "Error: No .stp or .step files found in input directory: " << input_dir << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(output_dir) && !std::filesystem::is_directory(output_dir)) {
|
||||
std::cerr << "Error: When --stp is a directory, --glb must be a directory path.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::filesystem::create_directories(output_dir);
|
||||
|
||||
const auto compressed_glb_cli = app.get_option("--compressed-glb")->as<std::string>();
|
||||
const std::filesystem::path compressed_glb_base = compressed_glb_cli.empty()
|
||||
? std::filesystem::path{}
|
||||
: std::filesystem::path(compressed_glb_cli);
|
||||
if (!compressed_glb_base.empty() &&
|
||||
std::filesystem::exists(compressed_glb_base) &&
|
||||
!std::filesystem::is_directory(compressed_glb_base)) {
|
||||
std::cerr << "Error: In batch mode, --compressed-glb must be a directory path when it already exists.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!compressed_glb_base.empty()) {
|
||||
std::filesystem::create_directories(compressed_glb_base);
|
||||
}
|
||||
|
||||
std::cout << "Batch mode enabled" << "\n";
|
||||
std::cout << "Input directory: " << input_dir << "\n";
|
||||
std::cout << "Output directory: " << output_dir << "\n";
|
||||
std::cout << "Files to convert: " << step_files.size() << "\n";
|
||||
|
||||
int success_count = 0;
|
||||
std::vector<std::string> failed_files;
|
||||
|
||||
for (size_t index = 0; index < step_files.size(); ++index) {
|
||||
const auto& stp_file = step_files[index];
|
||||
auto glb_file_name = stp_file.stem();
|
||||
glb_file_name += ".glb";
|
||||
const auto glb_file = output_dir / glb_file_name;
|
||||
|
||||
std::filesystem::path compressed_glb_file;
|
||||
if (!compressed_glb_base.empty()) {
|
||||
auto compressed_file_name = stp_file.stem();
|
||||
compressed_file_name += ".glb";
|
||||
compressed_glb_file = compressed_glb_base / compressed_file_name;
|
||||
}
|
||||
|
||||
std::cout << "============================================================" << "\n";
|
||||
std::cout << "[" << (index + 1) << "/" << step_files.size() << "] "
|
||||
<< stp_file.filename() << " -> " << glb_file.filename() << "\n";
|
||||
|
||||
GlobalConfig config;
|
||||
try {
|
||||
config = process_parameters(app, stp_file, glb_file, compressed_glb_file);
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << "\n";
|
||||
failed_files.push_back(stp_file.filename().string());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (run_conversion(config) == 0) {
|
||||
++success_count;
|
||||
} else {
|
||||
failed_files.push_back(stp_file.filename().string());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "============================================================" << "\n";
|
||||
std::cout << "Batch completed: success " << success_count
|
||||
<< ", failed " << failed_files.size() << "\n";
|
||||
if (!failed_files.empty()) {
|
||||
std::cout << "Failed files:" << "\n";
|
||||
for (const auto& failed_file : failed_files) {
|
||||
std::cout << " - " << failed_file << "\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print_status(const GlobalConfig& config) {
|
||||
std::cout << "STP2GLB Converter" << "\n";
|
||||
std::cout << "STP File: " << config.stpFile << "\n";
|
||||
@ -129,6 +288,11 @@ int main(int argc, char* argv[])
|
||||
app.get_option("--stp")->required();
|
||||
app.get_option("--glb")->required();
|
||||
|
||||
const std::filesystem::path stp_input = app.get_option("--stp")->results()[0];
|
||||
if (std::filesystem::exists(stp_input) && std::filesystem::is_directory(stp_input)) {
|
||||
return run_batch_conversion(app);
|
||||
}
|
||||
|
||||
GlobalConfig config;
|
||||
try {
|
||||
config = process_parameters(app);
|
||||
@ -137,44 +301,5 @@ int main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_status(config);
|
||||
std::cout << "\n";
|
||||
std::cout << "Starting conversion..." << "\n";
|
||||
|
||||
const auto start = std::chrono::high_resolution_clock::now();
|
||||
try {
|
||||
if (config.buildConfig.build_bspline_surf)
|
||||
make_a_bspline_surf(config);
|
||||
|
||||
if (config.debug_mode == 1)
|
||||
debug_stp_to_glb(config);
|
||||
else
|
||||
{
|
||||
convert_stp_to_glb(config);
|
||||
}
|
||||
|
||||
apply_gltfpack_compression(config);
|
||||
} catch (std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto stop = std::chrono::high_resolution_clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
|
||||
const double seconds = static_cast<double>(duration.count()) / 1e6;
|
||||
std::cout << "STP converted in: " << std::fixed << std::setprecision(2) << seconds << " seconds" << "\n";
|
||||
|
||||
// Clean up downloaded temporary file
|
||||
if (config.is_downloaded_from_url) {
|
||||
try {
|
||||
if (std::filesystem::exists(config.stpFile)) {
|
||||
std::filesystem::remove(config.stpFile);
|
||||
std::cout << "Cleaned up downloaded file: " << config.stpFile << "\n";
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "Warning: Failed to clean up downloaded file: " << ex.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return run_conversion(config);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user