Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.

Commit 4811f8d

Browse files
committed
Added pyfqmr, replaced many bpy with bmesh operations & added better dependency management
Added pyfqmr and xatlas submodules Added in-place install/build of submodules Added GitHub Actions based CD Pipeline Added "Render Device" Option Added "Lower Resolution By LOD" Option Addded pyfqmr based reduction Added more meaningful console outputs across all plugins. Added styling for QCheckboxes in style.qss Refactored Performance Critical Operations to use BMesh instead of bpy.ops Refactored runtime dependency management Tweaked Range for Ray Distance to support larger models. Updated README.md Updated requirements.txt Updated .gitignore
1 parent 38e883b commit 4811f8d

18 files changed

Lines changed: 1282 additions & 283 deletions
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
jobs:
9+
build-and-release:
10+
runs-on: ubuntu-latest
11+
12+
container:
13+
image: alpine:latest
14+
15+
steps:
16+
- name: Install Dependencies
17+
run: |
18+
apk add --no-cache git zip bash python3 python3-dev py3-pip build-base
19+
20+
- name: Check out code with submodules
21+
uses: actions/checkout@v4
22+
with:
23+
submodules: true
24+
25+
- name: Build Python Modules in enviro_lod_tools/external
26+
run: |
27+
# Navigate to the external directory
28+
cd enviro_lod_tools/external
29+
30+
# List of submodule directories (assuming they are direct subdirectories)
31+
for dir in */ ; do
32+
if [ -f "$dir/setup.py" ]; then
33+
echo "Building Python module in $dir"
34+
cd "$dir"
35+
# Install the module in a temporary location
36+
python3 setup.py build
37+
python3 setup.py install --root=../../../../temp_installation
38+
cd ..
39+
fi
40+
done
41+
42+
- name: Clean Up Unnecessary Files in enviro_lod_tools/external
43+
run: |
44+
cd enviro_lod_tools/external
45+
# Remove build directories and any other unnecessary files
46+
find . -type d -name '__pycache__' -exec rm -r {} +
47+
find . -type d -name 'build' -exec rm -r {} +
48+
find . -type d -name 'dist' -exec rm -r {} +
49+
find . -type f -name '*.pyc' -delete
50+
# Remove setup files if not needed
51+
find . -type f -name 'setup.py' -delete
52+
find . -type f -name 'setup.cfg' -delete
53+
find . -type f -name 'MANIFEST.in' -delete
54+
cd ../..
55+
56+
- name: Move Installed Modules Back to enviro_lod_tools/external
57+
run: |
58+
# Copy the installed modules back to the external directory
59+
cp -r temp_installation/usr/local/lib/python3*/site-packages/* enviro_lod_tools/external/
60+
# Remove the temporary installation directory
61+
rm -rf temp_installation
62+
63+
- name: Get Tag Name
64+
id: get_tag
65+
shell: bash
66+
run: |
67+
TAG=$(git describe --tags --exact-match)
68+
echo "TAGS: $TAG"
69+
if [ -z "$TAG" ]; then
70+
echo "No tags on this commit."
71+
echo "TAG=" >> $GITHUB_ENV
72+
else
73+
echo "Found tag: $TAG"
74+
echo "TAG=$TAG" >> $GITHUB_ENV
75+
fi
76+
77+
- name: Exit if No Tag
78+
if: env.TAG == ''
79+
run: |
80+
echo "No valid tag found on this commit. Exiting."
81+
exit 0
82+
83+
- name: Create enviro_lod_tools_plugin_${{ env.TAG }}.zip
84+
if: env.TAG != ''
85+
run: |
86+
cd enviro_lod_tools
87+
zip -r ../enviro_lod_tools_plugin_${TAG}.zip .
88+
cd ..
89+
90+
- name: Create enviro_lod_tools_gui_${{ env.TAG }}.zip
91+
if: env.TAG != ''
92+
run: |
93+
zip -r enviro_lod_tools_gui_${TAG}.zip .
94+
95+
- name: Create GitHub Release
96+
if: env.TAG != ''
97+
id: create_release
98+
uses: actions/create-release@v1
99+
with:
100+
tag_name: ${{ env.TAG }}
101+
release_name: Release ${{ env.TAG }}
102+
draft: false
103+
prerelease: true
104+
105+
- name: Upload Release Asset - Plugin Zip
106+
if: env.TAG != ''
107+
uses: actions/upload-release-asset@v1
108+
with:
109+
upload_url: ${{ steps.create_release.outputs.upload_url }}
110+
asset_path: enviro_lod_tools_plugin_${{ env.TAG }}.zip
111+
asset_name: enviro_lod_tools_plugin_${{ env.TAG }}.zip
112+
asset_content_type: application/zip
113+
114+
- name: Upload Release Asset - GUI Zip
115+
if: env.TAG != ''
116+
uses: actions/upload-release-asset@v1
117+
with:
118+
upload_url: ${{ steps.create_release.outputs.upload_url }}
119+
asset_path: enviro_lod_tools_gui_${{ env.TAG }}.zip
120+
asset_name: enviro_lod_tools_gui_${{ env.TAG }}.zip
121+
asset_content_type: application/zip

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,6 @@ dmypy.json
8484
# Extension
8585

8686
enviro_lod_tools.zip
87+
experimental/
8788

8889
# End of template

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "enviro_lod_tools/external/pyfqmr"]
2+
path = enviro_lod_tools/external/pyfqmr
3+
url = https://github.com/Kramer84/pyfqmr-Fast-Quadric-Mesh-Reduction.git
4+
[submodule "enviro_lod_tools/external/xatlas"]
5+
path = enviro_lod_tools/external/xatlas
6+
url = https://github.com/mworchel/xatlas-python.git

README.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,25 @@ This is a collection of plugins for [Blender](https://www.blender.org/) (v. 4.0.
88
The plugins are designed to help with the creation of environment levels of detail (LODs) for terrestrial photogrammetry models.
99
(Models of Landscapes, Cities, and other "flat" structures).
1010

11-
The plugin is split into several single plugins, that can be used independently of each other.
11+
The tool is split into several single plugins, that can be used independently of each other.
1212
There is also a combined plugin that can load a model from the file system and generate LODs for it, without actively rendering it to the viewport.
1313
**This is essential for source files that are too massive to display in the viewport.**
1414

1515
### Features
1616

17-
- **Cleanup**: Cleans/Preprocesses the mesh for use in the LOD pipeline.
17+
- **Cleanup**: Cleans/Preprocesses the mesh for use in the LOD pipeline. All mesh operations are done using the BMesh framework to ensure performance. [Pyfqmr](https://github.com/Kramer84/pyfqmr-Fast-Quadric-Mesh-Reduction) is used for mesh reduction.
18+
19+
1820
- **Mesh Slicer**: Cuts a mesh into a user-defined amount of square slices. (This reimplements Blenders Bisect logic in a way that does not require to duplicate the mesh in order to keep both halfs)
19-
- **LOD Pipeline**: Generates the levels of detail (LODs) for all the selections using the provided settings. The LOD generation retains the borders of the highest LOD for flawless LOD transitions of individual modules.
21+
22+
23+
- **LOD Pipeline**: Generates the levels of detail (LODs) for all the selections using [pyfqmr](https://github.com/Kramer84/pyfqmr-Fast-Quadric-Mesh-Reduction) again. The LOD generation retains the borders of the highest LOD for flawless LOD transitions of individual modules.
24+
25+
2026
- **XAtlas Unwrapper**: Unwraps the model using the [xatlas-python](https://github.com/mworchel/xatlas-python) bindings.
21-
- **Baker**: Transfers the base color of a defined mesh onto one or multiple selected meshes.
27+
28+
29+
- **Baker**: Transfers the base color of a defined mesh onto one or multiple selected meshes. Blender is used as the baking framework.
2230

2331

2432
# Installation
@@ -32,25 +40,31 @@ EnvironmentLodTools can also be used with a "standalone" PySide6 based GUI.
3240
It exposes the exact same parameters, but uses the users local Python install, with Blender as a module, instead of Blenders Embedded Python.
3341

3442
To use the GUI do the following:
35-
1. Download the entire `source code` from the [latest release](https://github.com/gojushin/EnvironmentLodTool/releases/latest).
43+
1. Download the entire `source code` from the [latest release](https://github.com/gojushin/EnvironmentLodTools/releases).
3644
2. Open the command prompt.
3745
3. Run `pip install -r requirnments.txt` in the directory of the plugin.
3846
4. Start the GUI by executing `enviro_tools_gui.py`
3947

48+
Note: When starting the GUI for the first time, it will take a few moments to build the python modules.
49+
4050
## Plugin
4151
To install the plugins, follow these steps:
4252

4353
1. Download the [latest release](https://github.com/gojushin/EnvironmentLodTool/releases/latest) from GitHub.
4454
2. In Blender, go to `Edit` -> `Preferences` -> `Add-ons` and click on the `Install` button.
4555
3. Select the .zip file from the download folder.
46-
4. Enable the plugins by checking the plugins checkbox. *Note: This invokes pip to install xatlas to blenders environment and can therefore cause Blender to hang for a second.*
56+
4. Enable the plugins by checking the plugins checkbox.
57+
58+
*Note: Enabling the plugins for the first time will take a few moments since two python modules will be built in place in Blenders Python install.*
4759

4860
### Usage
4961

5062
Once installed, the plugins can be accessed through the `Tool` and `Tools` panel.
5163

5264
To use the GUI, download the source code and execute the `enviro_tools_gui.py` file.
53-
_Note: Since Blender is non-thread safe by nature, the GUI will currently freeze. You can track the progress in the CLI._
65+
66+
_Note: Since Blender is non-thread safe by nature, the GUI will currently freeze upon starting the pipeline.
67+
You can track the progress in the CLI._
5468

5569
### Contributing
5670

@@ -63,3 +77,17 @@ The code is licensed under the [GPLv3 License](LICENSE).
6377
### Credits
6478

6579
This project was created by [Nico Breycha](https://github.com/gojushin).
80+
81+
3rd party libraries used in this project are licensed under their own licenses.
82+
- [xatlas-python](https://github.com/mworchel/xatlas-python) bindings, licensed under the [MIT License](https://github.com/mworchel/xatlas-python/blob/master/LICENSE).
83+
- (Original [xatlas](https://github.com/jpcy/xatlas) Implementation by [jpcy](https://github.com/jpcy))
84+
85+
86+
- [pyfqmr](https://github.com/Kramer84/pyfqmr-Fast-Quadric-Mesh-Reduction), licensed under the [MIT License](https://github.com/Kramer84/pyfqmr-Fast-Quadric-Mesh-Reduction/blob/master/LICENSE)
87+
- (Original [Fast-Quadric-Mesh-Simplification](https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification) implementation by [sp4cerat](https://github.com/sp4cerat))
88+
89+
90+
- [Blender](https://www.blender.org/), licensed under the [GPLv2 License](https://www.blender.org/about/license/)
91+
92+
93+
- [Pyside6](https://pypi.org/project/PySide6/), licensed under the [LGPLv3/GPLv3](https://github.com/pyside6/pyside6/blob/master/LICENSE)

deploy.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import os
22
import zipfile
33

4+
PLUGIN_FOLDER_NAME = "enviro_lod_tools"
45

56
def zip_directory(directory):
67
"""
7-
Zips all files in a directory.
8+
Zips all files in a directory, excluding __pycache__.
89
:param directory: The directory to zip.
910
:type directory: str
1011
"""
1112
zip_filename = f"{directory}.zip"
1213
with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
1314
for root, dirs, files in os.walk(directory):
15+
dirs[:] = [d for d in dirs if d != '__pycache__'] # Exclude __pycache__ directory
1416
for file in files:
1517
file_path = os.path.join(root, file)
1618
zipf.write(file_path, os.path.relpath(file_path, start=os.path.join(directory, '..')))
@@ -20,7 +22,7 @@ def zip_directory(directory):
2022
user_defined_folder = input("Enter the folder name within the current directory: ")
2123
if not user_defined_folder:
2224
# Get the first subdirectory in the current directory that is not a hidden directory
23-
user_defined_folder = [d for d in os.listdir() if os.path.isdir(d) and not d.startswith('.')][0]
25+
user_defined_folder = PLUGIN_FOLDER_NAME
2426
if os.path.isdir(user_defined_folder):
2527
zip_directory(user_defined_folder)
2628
print(f"Processed and zipped the directory {user_defined_folder} successfully.")

0 commit comments

Comments
 (0)