mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 00:07:24 +00:00
Merge branch 'devel' into devel-PFasano99
# Conflicts: # .github/workflows/BuildMeshLab.yml # src/vcglib
This commit is contained in:
commit
8724db38b3
23
.github/actions/0_setup/action.yml
vendored
Normal file
23
.github/actions/0_setup/action.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: 'Setup Environment'
|
||||
description: 'Setup Environment'
|
||||
|
||||
inputs:
|
||||
qt-version:
|
||||
description: 'Qt Version'
|
||||
required: false
|
||||
default: '5.15.2'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
cache: true
|
||||
version: ${{ inputs.qt-version }}
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/0_setup_env.sh --dont_install_qt
|
||||
56
.github/actions/1_build/action.yml
vendored
Normal file
56
.github/actions/1_build/action.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
name: 'Build'
|
||||
description: 'Build'
|
||||
|
||||
inputs:
|
||||
cache-path:
|
||||
description: 'Directory to cache after build'
|
||||
required: false
|
||||
default: ''
|
||||
cache-key:
|
||||
description: 'Cache key'
|
||||
required: false
|
||||
default: ''
|
||||
build-option:
|
||||
description: 'Build option'
|
||||
required: false
|
||||
default: ''
|
||||
nightly:
|
||||
description: 'Nightly build'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Setup env variables
|
||||
id: envs
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ inputs.build-option }}" != "" ]; then
|
||||
echo "build_option=--${{ inputs.build-option }}" >> $GITHUB_OUTPUT
|
||||
echo "artifact_suffix=_${{ inputs.build-option }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "build_option=" >> $GITHUB_OUTPUT
|
||||
echo "artifact_suffix=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
if [ "${{ inputs.nightly }}" = "true" ]; then
|
||||
echo "nightly=--nightly" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "nightly=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Cache external libraries sources
|
||||
id: cache-ext-libs
|
||||
if: ${{ inputs.cache-path != '' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ inputs.cache-path }}
|
||||
key: ${{ runner.os }}-${{ inputs.cache-key }}
|
||||
- name: Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ github.ref }}-${{ inputs.build-option }}
|
||||
- name: Configure and Build
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/1_build.sh ${{ steps.envs.outputs.build_option }} ${{ steps.envs.outputs.nightly }} --ccache
|
||||
65
.github/actions/2_deploy/action.yml
vendored
Normal file
65
.github/actions/2_deploy/action.yml
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
name: 'Deploy'
|
||||
description: 'Deploy'
|
||||
|
||||
inputs:
|
||||
mac-certificate:
|
||||
description: 'MacOS Certificate'
|
||||
required: false
|
||||
default: ''
|
||||
mac-certificate-id:
|
||||
description: 'MacOS Certificate ID'
|
||||
required: false
|
||||
default: ''
|
||||
mac-certificate-pssw:
|
||||
description: 'MacOS Certificate Password'
|
||||
required: false
|
||||
mac-notarization-user:
|
||||
description: 'MacOS Notarization User'
|
||||
required: false
|
||||
default: ''
|
||||
mac-notarization-team:
|
||||
description: 'MacOS Notarization Team'
|
||||
required: false
|
||||
default: ''
|
||||
mac-notarization-pssw:
|
||||
description: 'MacOS Notarization Password'
|
||||
required: false
|
||||
default: ''
|
||||
win-certificate:
|
||||
description: 'Windows Certificate'
|
||||
required: false
|
||||
default: ''
|
||||
win-certificate-pssw:
|
||||
description: 'Windows Certificate Password'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set Notarization settings
|
||||
id: notarization
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ inputs.mac-notarization-user }}" != "" ]; then
|
||||
echo "not_setting=--notarization_user='${{ inputs.mac-notarization-user }}' --notarization_team='${{ inputs.mac-notarization-team }}' --notarization_pssw='${{ inputs.mac-notarization-pssw }}'" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "not_setting=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Set CodeSign Certificate macOS
|
||||
if: ${{ runner.os == 'macOS' && inputs.mac-certificate != ''}}
|
||||
uses: apple-actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ inputs.mac-certificate }}
|
||||
p12-password: ${{ inputs.mac-certificate-pssw }}
|
||||
- name: Set CodeSign Certificate Windows
|
||||
shell: powershell
|
||||
if: ${{ runner.os == 'Windows' && inputs.win-certificate != '' }}
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ inputs.win-certificate }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
- name: Deploy
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/2_deploy.sh --cert_pssw='${{ inputs.win-certificate-pssw }}' --cert_id='${{ inputs.mac-certificate-id }}' ${{ steps.notarization.outputs.not_setting }}
|
||||
2
.github/stale.yml
vendored
2
.github/stale.yml
vendored
@ -51,7 +51,7 @@ markComment: >
|
||||
limitPerRun: 10
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
|
||||
56
.github/workflows/BuildMeshLab.yml
vendored
56
.github/workflows/BuildMeshLab.yml
vendored
@ -6,6 +6,7 @@ on:
|
||||
env:
|
||||
QT_VERSION: 5.15.2
|
||||
MAC_CERT: ${{secrets.MACOS_CERT_ID}}
|
||||
MAC_CERT_PSSW: ${{secrets.MACOS_CERTIFICATE_PSSW}}
|
||||
WIN_CERT: ${{secrets.WIN_CERTIFICATE}}
|
||||
|
||||
jobs:
|
||||
@ -21,29 +22,8 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Set CodeSign Certificate macOS
|
||||
if: runner.os == 'macOS' && env.MAC_CERT != null
|
||||
uses: apple-actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
p12-password: ${{ secrets.MACOS_CERTIFICATE_PSSW }}
|
||||
- name: Set CodeSign Certificate Windows
|
||||
if: runner.os == 'Windows' && env.WIN_CERT != null
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_CERTIFICATE }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
cache: true
|
||||
version: ${{ env.QT_VERSION }}
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/0_setup_env.sh --dont_install_qt
|
||||
- name: Setup Environment
|
||||
uses: ./.github/actions/0_setup
|
||||
- name: Setup env variables
|
||||
id: envs
|
||||
shell: bash
|
||||
@ -53,24 +33,20 @@ jobs:
|
||||
else
|
||||
echo "artifact_suffix=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Cache external libraries sources
|
||||
id: cache-ext-libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: src/external/downloads/*
|
||||
key: ${{ runner.os }}-external-libraries
|
||||
- name: Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ github.ref }}-${{ matrix.precision }}
|
||||
- name: Configure and Build
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} --nightly --ccache --use_brew_llvm
|
||||
- name: Build
|
||||
uses: ./.github/actions/1_build
|
||||
cache-path: src/external/downloads/*
|
||||
cache-key: external-libraries
|
||||
build-option: ${{matrix.precision}}
|
||||
nightly: true
|
||||
- name: Deploy
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/2_deploy.sh --cert_pssw='${{ secrets.WIN_CERTIFICATE_PSSW }}' --cert_id=${{ secrets.MACOS_CERT_ID }}
|
||||
uses: ./.github/actions/2_deploy
|
||||
with:
|
||||
mac-certificate: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
mac-certificate-id: ${{ secrets.MACOS_CERT_ID }}
|
||||
mac-certificate-pssw: ${{ secrets.MACOS_CERTIFICATE_PSSW }}
|
||||
win-certificate: ${{ secrets.WIN_CERTIFICATE }}
|
||||
win-certificate-pssw: ${{ secrets.WIN_CERTIFICATE_PSSW }}
|
||||
- name: Upload MeshLab Portable
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
76
.github/workflows/CreateRelease.yml
vendored
76
.github/workflows/CreateRelease.yml
vendored
@ -41,29 +41,8 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: main
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Set CodeSign Certificate macOS
|
||||
if: runner.os == 'macOS'
|
||||
uses: apple-actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
p12-password: ${{ secrets.MACOS_CERTIFICATE_PSSW }}
|
||||
- name: Set CodeSign Certificate Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_CERTIFICATE }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
cache: true
|
||||
version: ${{ env.QT_VERSION }}
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/0_setup_env.sh --dont_install_qt
|
||||
- name: Setup Environment
|
||||
uses: ./.github/actions/0_setup
|
||||
- name: Setup env variables
|
||||
id: envs
|
||||
shell: bash
|
||||
@ -73,44 +52,23 @@ jobs:
|
||||
else
|
||||
echo "artifact_suffix=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Cache external libraries sources
|
||||
id: cache-ext-libs
|
||||
uses: actions/cache@v3
|
||||
- name: Build
|
||||
uses: ./.github/actions/1_build
|
||||
with:
|
||||
path: src/external/downloads/*
|
||||
key: ${{ runner.os }}-external-libraries
|
||||
- name: Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ github.ref }}-${{ matrix.precision }}
|
||||
- name: Configure and Build
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} --ccache
|
||||
cache-path: src/external/downloads/*
|
||||
cache-key: external-libraries
|
||||
build-option: ${{matrix.precision}}
|
||||
- name: Deploy
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/${{ runner.os }}/2_deploy.sh --cert_pssw='${{ secrets.WIN_CERTIFICATE_PSSW }}' --cert_id=${{ secrets.MACOS_CERT_ID }}
|
||||
- name: Get AppBundle Name
|
||||
if: runner.os == 'macOS'
|
||||
id: abn
|
||||
shell: bash
|
||||
run: |
|
||||
cd install
|
||||
NAME=$(ls -d MeshLab*)
|
||||
echo "app_bundle_name=$NAME" >> $GITHUB_OUTPUT
|
||||
- name: Notarize macOS
|
||||
if: runner.os == 'macOS'
|
||||
uses: devbotsxyz/xcode-notarize@v1
|
||||
uses: ./.github/actions/2_deploy
|
||||
with:
|
||||
product-path: "install/${{steps.abn.outputs.app_bundle_name}}"
|
||||
appstore-connect-username: ${{ secrets.MACOS_NOTARIZATION_USER }}
|
||||
appstore-connect-password: ${{ secrets.MACOS_NOTARIZATION_PSSW }}
|
||||
- name: Staple Release macOS
|
||||
if: runner.os == 'macOS'
|
||||
uses: devbotsxyz/xcode-staple@v1
|
||||
with:
|
||||
product-path: "install/${{steps.abn.outputs.app_bundle_name}}"
|
||||
mac-certificate: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
mac-certificate-id: ${{ secrets.MACOS_CERT_ID }}
|
||||
mac-certificate-pssw: ${{ secrets.MACOS_CERTIFICATE_PSSW }}
|
||||
mac-notarization-user: ${{ secrets.MACOS_NOTARIZATION_USER }}
|
||||
mac-notarization-team: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
|
||||
mac-notarization-pssw: ${{ secrets.MACOS_NOTARIZATION_PSSW }}
|
||||
win-certificate: ${{ secrets.WIN_CERTIFICATE }}
|
||||
win-certificate-pssw: ${{ secrets.WIN_CERTIFICATE_PSSW }}
|
||||
- name: Upload MeshLab Portable
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@ -242,7 +200,7 @@ jobs:
|
||||
cd ..
|
||||
|
||||
#Create release and upload
|
||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
||||
- uses: "marvinpinto/action-automatic-releases@6273874b61ebc8c71f1a61b2d98e234cf389b303"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "MeshLab-${{steps.envs.outputs.ml_version}}"
|
||||
|
||||
@ -30,9 +30,9 @@ case $i in
|
||||
shift # past argument=value
|
||||
;;
|
||||
-cp=*|--cert_pssw=*)
|
||||
if [ -z "${i#*=}" ]; then
|
||||
CERT_PSSW="${i#*=}"
|
||||
if [ -n "$CERT_PSSW" ]; then
|
||||
SIGN=true
|
||||
CERT_PSSW="${i#*=}"
|
||||
fi
|
||||
shift # past argument=value
|
||||
;;
|
||||
@ -60,4 +60,4 @@ if [ "$SIGN" = true ] ; then
|
||||
bash $SCRIPTS_PATH/internal/2b_sign_dlls.sh -i=$PACKAGES_PATH $CERT_FILE_OPTION -cp=$CERT_PSSW
|
||||
|
||||
echo "======= Installer Signed ======="
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -6,7 +6,11 @@ INSTALL_PATH=$SCRIPTS_PATH/../../install
|
||||
QT_DIR_OPTION=""
|
||||
PACKAGES_PATH=$SCRIPTS_PATH/../../packages
|
||||
SIGN=false
|
||||
NOTARIZE=false
|
||||
CERT_ID=""
|
||||
NOTAR_USER=""
|
||||
NOTAR_TEAM_ID=""
|
||||
NOTAR_PASSWORD=""
|
||||
|
||||
#checking for parameters
|
||||
for i in "$@"
|
||||
@ -25,12 +29,27 @@ case $i in
|
||||
shift # past argument=value
|
||||
;;
|
||||
-ci=*|--cert_id=*)
|
||||
if [ -z "${i#*=}" ]; then
|
||||
SIGN=true
|
||||
CERT_ID="${i#*=}"
|
||||
CERT_ID="${i#*=}"
|
||||
if [ -n "$CERT_ID" ]; then
|
||||
SIGN=true
|
||||
fi
|
||||
shift # past argument=value
|
||||
;;
|
||||
-nu=*|--notarization_user=*)
|
||||
NOTAR_USER="${i#*=}"
|
||||
if [ -n "$NOTAR_USER" ]; then
|
||||
NOTARIZE=true
|
||||
fi
|
||||
shift # past argument=value
|
||||
;;
|
||||
-np=*|--notarization_pssw=*)
|
||||
NOTAR_PASSWORD="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-nt=*|--notarization_team=*)
|
||||
NOTAR_TEAM_ID="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
@ -47,6 +66,12 @@ if [ "$SIGN" = true ] ; then
|
||||
echo "======= AppBundle Signed ======="
|
||||
fi
|
||||
|
||||
bash $SCRIPTS_PATH/internal/2c_dmg.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH
|
||||
if [ "$NOTARIZE" = true ] ; then
|
||||
bash $SCRIPTS_PATH/internal/2c_notarize_appbundle.sh -i=$INSTALL_PATH -nu=$NOTAR_USER -nt=$NOTAR_TEAM_ID -np=$NOTAR_PASSWORD
|
||||
|
||||
echo "======= AppBundle Notarized ======="
|
||||
fi
|
||||
|
||||
bash $SCRIPTS_PATH/internal/2d_dmg.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH
|
||||
|
||||
echo "======= DMG Created ======="
|
||||
@ -23,4 +23,6 @@ case $i in
|
||||
esac
|
||||
done
|
||||
|
||||
codesign --options "runtime" --timestamp --force --deep --sign $CERT_ID $INSTALL_PATH/meshlab.app
|
||||
codesign --options "runtime" --timestamp --force --deep --sign $CERT_ID $INSTALL_PATH/meshlab.app
|
||||
|
||||
spctl -a -vvv $INSTALL_PATH/meshlab.app
|
||||
44
scripts/macOS/internal/2c_notarize_appbundle.sh
Normal file
44
scripts/macOS/internal/2c_notarize_appbundle.sh
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/..
|
||||
|
||||
INSTALL_PATH=$SCRIPTS_PATH/../../install
|
||||
NOTAR_USER=""
|
||||
NOTAR_PASSWORD=""
|
||||
NOTAR_TEAM_ID=""
|
||||
|
||||
#checking for parameters
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
-i=*|--install_path=*)
|
||||
INSTALL_PATH="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-nu=*|--notarization_user=*)
|
||||
NOTAR_USER="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-nt=*|--notarization_team=*)
|
||||
NOTAR_TEAM_ID="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-np=*|--notarization_pssw=*)
|
||||
NOTAR_PASSWORD="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id $NOTAR_USER --team-id $NOTAR_TEAM_ID --password $NOTAR_PASSWORD
|
||||
|
||||
ditto -c -k --keepParent "$INSTALL_PATH/meshlab.app" "$INSTALL_PATH/notarization.zip"
|
||||
|
||||
xcrun notarytool submit "install/notarization.zip" --keychain-profile "notarytool-profile" --wait
|
||||
|
||||
xcrun stapler staple "$INSTALL_PATH/meshlab.app"
|
||||
|
||||
rm -rf $INSTALL_PATH/notarization.zip
|
||||
@ -153,7 +153,7 @@ if(NOT DEFINED MESHLAB_PLUGINS) # it may be already defined in parent directory
|
||||
meshlabplugins/filter_dirt
|
||||
meshlabplugins/filter_embree
|
||||
meshlabplugins/filter_fractal
|
||||
meshlabplugins/filter_func
|
||||
meshlabplugins/filter_func
|
||||
meshlabplugins/filter_img_patch_param
|
||||
meshlabplugins/filter_icp
|
||||
meshlabplugins/filter_io_nxs
|
||||
|
||||
@ -18,7 +18,7 @@ set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||
|
||||
### Settings needed for both "external" and internal code
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
@ -82,18 +82,31 @@ LayerDialog::LayerDialog(QWidget *parent )
|
||||
// The following connection is used to associate the click with the switch between raster and mesh view.
|
||||
connect(ui->rasterTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem * , int )) , this, SLOT(rasterItemClicked(QTreeWidgetItem * , int ) ) );
|
||||
|
||||
// state buttons
|
||||
// state and animation buttons
|
||||
isRecording = false;
|
||||
viewState[0] = viewState[1] = viewState[2] = viewState[3] = "";
|
||||
connect(ui->bW1, SIGNAL(clicked()), this, SLOT(clickW1()));
|
||||
connect(ui->bW2, SIGNAL(clicked()), this, SLOT(clickW2()));
|
||||
connect(ui->bW3, SIGNAL(clicked()), this, SLOT(clickW3()));
|
||||
connect(ui->bW4, SIGNAL(clicked()), this, SLOT(clickW4()));
|
||||
connect(ui->animSlower, SIGNAL(clicked()), this, SLOT(clickAnimSlower()));
|
||||
connect(ui->animStepBackward, SIGNAL(clicked()), this, SLOT(clickAnimStepBackward()));
|
||||
connect(ui->animPlay, SIGNAL(clicked()), this, SLOT(clickAnimPlay()));
|
||||
connect(ui->animStepForward, SIGNAL(clicked()), this, SLOT(clickAnimStepForward()));
|
||||
connect(ui->animFaster, SIGNAL(clicked()), this, SLOT(clickAnimFaster()));
|
||||
connect(ui->bV1, SIGNAL(clicked()), this, SLOT(clickV1()));
|
||||
connect(ui->bV2, SIGNAL(clicked()), this, SLOT(clickV2()));
|
||||
connect(ui->bV3, SIGNAL(clicked()), this, SLOT(clickV3()));
|
||||
connect(ui->bV4, SIGNAL(clicked()), this, SLOT(clickV4()));
|
||||
|
||||
animIndex = -1;
|
||||
animMsecDelay = 500;
|
||||
animTimer = new QTimer(this);
|
||||
resetAnim();
|
||||
connect(animTimer, SIGNAL(timeout()), this, SLOT(updateAnim()));
|
||||
// Make wide enough to accommodate alternate text ("||") from clickAnimPlay()
|
||||
ui->animPlay->setMinimumSize(ui->animPlay->size().width() + 6, ui->animPlay->size().height());
|
||||
|
||||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
ui->meshTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
ui->rasterTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
@ -219,6 +232,61 @@ void LayerDialog::clickW4()
|
||||
mw->meshDoc()->Log.log(0, "No View to Restore");
|
||||
}
|
||||
|
||||
void LayerDialog::clickAnimSlower()
|
||||
{
|
||||
if (animMsecDelay < 3000)
|
||||
{
|
||||
animMsecDelay = int(animMsecDelay * 1.2);
|
||||
}
|
||||
}
|
||||
|
||||
void LayerDialog::clickAnimStepBackward()
|
||||
{
|
||||
pauseAnim();
|
||||
stepAnim(-1);
|
||||
}
|
||||
|
||||
void LayerDialog::clickAnimPlay()
|
||||
{
|
||||
if (!animTimer->isActive() && startAnim())
|
||||
{
|
||||
ui->animPlay->setText(tr("||"));
|
||||
ui->animPlay->setToolTip(tr("Pause animation"));
|
||||
stepAnim(1);
|
||||
animTimer->start(animMsecDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
pauseAnim();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerDialog::clickAnimStepForward()
|
||||
{
|
||||
pauseAnim();
|
||||
stepAnim(1);
|
||||
}
|
||||
|
||||
void LayerDialog::clickAnimFaster()
|
||||
{
|
||||
if (animMsecDelay > 10)
|
||||
{
|
||||
animMsecDelay = int(animMsecDelay / 1.2f);
|
||||
}
|
||||
}
|
||||
|
||||
void LayerDialog::updateAnim()
|
||||
{
|
||||
if (stepAnim(1) > 1)
|
||||
{
|
||||
animTimer->start(animMsecDelay); // Restart in case animMsecDelay changed
|
||||
}
|
||||
else
|
||||
{
|
||||
pauseAnim();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerDialog::clickV1()
|
||||
{
|
||||
MeshDocument *md = mw->meshDoc();
|
||||
@ -406,6 +474,13 @@ void LayerDialog::meshItemClicked (QTreeWidgetItem * item , int col)
|
||||
mw->GLA()->meshSetVisibility(*md->getMesh(clickedId), !md->getMesh(clickedId)->isVisible());
|
||||
}
|
||||
updatePerMeshItemVisibility();
|
||||
|
||||
// If not animating, or a mesh in the animation set was clicked, reset the animation
|
||||
if (!ui->animPlay->isChecked() ||
|
||||
std::find(animMeshIDs.begin(), animMeshIDs.end(), clickedId) != animMeshIDs.end())
|
||||
{
|
||||
resetAnim();
|
||||
}
|
||||
} break;
|
||||
case 1 :
|
||||
|
||||
@ -676,6 +751,28 @@ void LayerDialog::updateTable(const MLSceneGLSharedDataContext::PerMeshRendering
|
||||
}
|
||||
_docitem->addChildren(itms);
|
||||
|
||||
// Delete any animation IDs no longer in the layer dialog
|
||||
for (auto animIter = animMeshIDs.begin(); animIter != animMeshIDs.end(); )
|
||||
{
|
||||
bool foundInMeshList = false;
|
||||
for(MeshModel& m : md->meshIterator())
|
||||
{
|
||||
if (m.id() == *animIter)
|
||||
{
|
||||
foundInMeshList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundInMeshList)
|
||||
{
|
||||
++animIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
animIter = animMeshIDs.erase(animIter);
|
||||
}
|
||||
}
|
||||
|
||||
updateTreeWidgetSizes(ui->meshTreeWidget);
|
||||
updatePerMeshItemVisibility();
|
||||
updatePerMeshItemSelectionStatus();
|
||||
@ -861,6 +958,114 @@ void LayerDialog::actionActivated(MLRenderingAction* ract)
|
||||
_tabw->switchTab(ract->meshId(),ract->text());
|
||||
}
|
||||
|
||||
bool LayerDialog::startAnim()
|
||||
{
|
||||
if (animMeshIDs.size() > 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MeshDocument *md = mw->meshDoc();
|
||||
bool canAnimate = md->meshNumber() > 1;
|
||||
|
||||
if (canAnimate)
|
||||
{
|
||||
int visibleCount = 0;
|
||||
for(MeshModel& m : md->meshIterator())
|
||||
{
|
||||
if (m.isVisible())
|
||||
{
|
||||
++visibleCount;
|
||||
}
|
||||
}
|
||||
// If fewer than two meshes were visible select all meshes, else select only the visible ones
|
||||
animIndex = -1;
|
||||
animMeshIDs.clear();
|
||||
for(MeshModel& m : md->meshIterator())
|
||||
{
|
||||
if (m.isVisible() && animIndex < 0)
|
||||
{
|
||||
animIndex = animMeshIDs.size(); // Remember first visible mesh
|
||||
}
|
||||
if (m.isVisible() || visibleCount < 2)
|
||||
{
|
||||
animMeshIDs.push_back(m.id());
|
||||
}
|
||||
}
|
||||
if (animIndex >= 0)
|
||||
{
|
||||
--animIndex;
|
||||
}
|
||||
ui->animStepBackward->setEnabled(true);
|
||||
ui->animStepForward->setEnabled(true);
|
||||
}
|
||||
return canAnimate;
|
||||
}
|
||||
|
||||
// Advance the animation by the specified offset (1 = forward, -1 = backward)
|
||||
int LayerDialog::stepAnim(int offset)
|
||||
{
|
||||
bool foundVisible = false;
|
||||
int animatingCount = 0;
|
||||
MeshDocument *md = mw->meshDoc();
|
||||
|
||||
if (md->meshNumber() > 1)
|
||||
{
|
||||
MeshModel* lastMP = nullptr;
|
||||
|
||||
while (!foundVisible && animMeshIDs.size() > 1)
|
||||
{
|
||||
animIndex = (animMeshIDs.size() + animIndex + offset) % animMeshIDs.size();
|
||||
animatingCount = 0;
|
||||
for (const auto& id : animMeshIDs)
|
||||
{
|
||||
for(MeshModel& m : md->meshIterator())
|
||||
{
|
||||
if (m.id() == id)
|
||||
{
|
||||
bool makeVisible = m.id() == animMeshIDs[animIndex];
|
||||
mw->GLA()->meshSetVisibility(m, makeVisible);
|
||||
foundVisible |= makeVisible;
|
||||
++animatingCount;
|
||||
lastMP = &m;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundVisible)
|
||||
{
|
||||
// The mesh being animated to was deleted; remove it from the list and try again
|
||||
animMeshIDs.erase(animMeshIDs.begin() + animIndex);
|
||||
animIndex -= offset;
|
||||
}
|
||||
}
|
||||
if (animMeshIDs.size() == 1 && lastMP != nullptr)
|
||||
{
|
||||
mw->GLA()->meshSetVisibility(*lastMP, true);
|
||||
}
|
||||
updatePerMeshItemVisibility();
|
||||
updatePerMeshItemSelectionStatus();
|
||||
mw->GLA()->update();
|
||||
}
|
||||
return animatingCount;
|
||||
}
|
||||
|
||||
void LayerDialog::pauseAnim()
|
||||
{
|
||||
animTimer->stop();
|
||||
ui->animPlay->setChecked(false);
|
||||
ui->animPlay->setText(tr(">"));
|
||||
ui->animPlay->setToolTip(tr("Resume animation"));
|
||||
}
|
||||
|
||||
void LayerDialog::resetAnim()
|
||||
{
|
||||
pauseAnim();
|
||||
animMeshIDs.clear();
|
||||
ui->animStepBackward->setEnabled(false);
|
||||
ui->animStepForward->setEnabled(false);
|
||||
ui->animPlay->setToolTip(tr("Animate visible meshes, or all if < 2 are visible"));
|
||||
}
|
||||
|
||||
LayerDialog::~LayerDialog()
|
||||
{
|
||||
delete ui;
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include <QTabWidget>
|
||||
#include <QGroupBox>
|
||||
#include <QCheckBox>
|
||||
#include <QTimer>
|
||||
#include <common/parameters/rich_parameter_list.h>
|
||||
#include <common/ml_shared_data_context/ml_shared_data_context.h>
|
||||
#include "ml_render_gui.h"
|
||||
@ -140,6 +141,12 @@ public slots:
|
||||
void clickW2();
|
||||
void clickW3();
|
||||
void clickW4();
|
||||
void clickAnimSlower();
|
||||
void clickAnimStepBackward();
|
||||
void clickAnimPlay();
|
||||
void clickAnimStepForward();
|
||||
void clickAnimFaster();
|
||||
void updateAnim();
|
||||
void clickV1();
|
||||
void clickV2();
|
||||
void clickV3();
|
||||
@ -177,6 +184,16 @@ private:
|
||||
QString viewState[4];
|
||||
QMap<int, bool> visibilityState[4];
|
||||
|
||||
int animIndex;
|
||||
std::vector<int> animMeshIDs;
|
||||
int animMsecDelay;
|
||||
QTimer* animTimer;
|
||||
|
||||
bool startAnim();
|
||||
int stepAnim(int offset);
|
||||
void pauseAnim();
|
||||
void resetAnim();
|
||||
|
||||
QTreeWidgetItem* _docitem;
|
||||
int _previd;
|
||||
QGroupBox* _renderingtabcontainer;
|
||||
|
||||
@ -139,7 +139,105 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="animSlower">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Decrease animation speed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="animStepBackward">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Animate one step backward</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="animPlay">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>></string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="animStepForward">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Animate one step forward</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="animFaster">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Increase animation speed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
|
||||
@ -22,17 +22,33 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "filter_func.h"
|
||||
#include <random>
|
||||
#include <vcg/complex/algorithms/create/platonic.h>
|
||||
|
||||
#include <vcg/complex/algorithms/create/marching_cubes.h>
|
||||
#include <vcg/complex/algorithms/create/mc_trivial_walker.h>
|
||||
|
||||
#include "muParser.h"
|
||||
#include "string_conversion.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
using namespace mu;
|
||||
using namespace vcg;
|
||||
|
||||
std::random_device randomDev;
|
||||
std::default_random_engine rndEngine(randomDev());
|
||||
//Function to generate a random double number in [0..1) interval
|
||||
double ML_Rnd() { return std::generate_canonical<double, 24>(rndEngine); }
|
||||
//Function to generate a random integer number in [0..a) interval
|
||||
double ML_RandInt(const double a) { return std::floor(a*ML_Rnd()); }
|
||||
|
||||
//Add rnd() and randint() custom functions to a mu::Parser
|
||||
void setCustomFunctions(mu::Parser& p)
|
||||
{
|
||||
p.DefineFun("rnd", ML_Rnd);
|
||||
p.DefineFun("randInt", ML_RandInt);
|
||||
}
|
||||
|
||||
// Constructor
|
||||
FilterFunctionPlugin::FilterFunctionPlugin()
|
||||
{
|
||||
@ -123,32 +139,47 @@ QString FilterFunctionPlugin::pythonFilterName(ActionIDType f) const
|
||||
}
|
||||
|
||||
const QString PossibleOperators(
|
||||
"<br>It's possible to use parenthesis <b>()</b>, and predefined operators:<br>"
|
||||
"<br>It's possible to use any of the predefined muparser built-in "
|
||||
"<a href='https://beltoforion.de/en/muparser/features.php#idDef2'>operators</a> and "
|
||||
"<a href='https://beltoforion.de/en/muparser/features.php#idDef1'>functions</a>, like: "
|
||||
"<b>&&</b> (logic and), <b>||</b> (logic or), <b><</b>, <b><=</b>, <b>></b>, <b>>=</b>, "
|
||||
"<b>!=</b> (not equal), <b>==</b> (equal), <b>_?_:_</b> (c/c++ ternary operator)<br><br>");
|
||||
"<b>!=</b> (not equal), <b>==</b> (equal), <b>_?_:_</b> (c/c++ ternary operator), and "
|
||||
"<b>rnd()</b> (random value in [0..1]), and these values:" );
|
||||
|
||||
const QString PerVertexAttributeString(
|
||||
"It's possible to use the following per-vertex variables in the expression:<br>"
|
||||
"<ul><li>Per-vertex variables:<br>"
|
||||
"<b>x,y,z</b> (position), <b>nx,ny,nz</b> (normal), <b>r,g,b,a</b> (color), <b>q</b> "
|
||||
"(quality), <b>vi</b> (vertex index), <b>vtu,vtv,ti</b> (texture coords and texture "
|
||||
"index), <b>vsel</b> (is the vertex selected? 1 yes, 0 no) "
|
||||
"and all custom <i>vertex attributes</i> already defined by user."
|
||||
"Point3 attribute are available as three variables with _x, _y, _z appended to the attribute name.<br>");
|
||||
"index), <b>vsel</b> ( 1 if selected, 0 if not selected)."
|
||||
"</li><li>Bounding Box variables:<br>"
|
||||
"<b>xmin,ymin,zmin</b> (min coordinates), <b>xmax,ymax,zmax</b> (max coordinates), "
|
||||
"<b>xmid,ymid,zmid</b> (midpoint coordinates), <b>xdim,ydim,zdim</b> (dimensions), "
|
||||
"<b>bbdiag</b> (diagonal length)"
|
||||
"</li><li>User-defined attributes:<br>"
|
||||
"All user defined custom <i>vertex attributes</i> are available. "
|
||||
"Point3 attribute are available as 3 variables with _x, _y, _z appended to the attribute name."
|
||||
"</li></ul>");
|
||||
|
||||
const QString PerFaceAttributeString(
|
||||
"It's possible to use the following per-face variables, or variables associated to the three "
|
||||
"vertex of every face:<br>"
|
||||
"<b>x0,y0,z0</b> for the first vertex position, <b>x1,y1,z1</b> for the second vertex "
|
||||
"position, <b>x2,y2,z2</b> for the third vertex position, "
|
||||
"<b>nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2</b> for vertex normals, <b>r0,g0,b0,a0 r1,g1,b1,a1 "
|
||||
"r2,g2,b2,a2</b> for vertex colors, <b>vi0, vi1, vi2</b> for vertex indices, "
|
||||
"<b>q0,q1,q2</b> for vertex quality, <b>wtu0,wtv0 wtu1,wtv1 wtu2,wtv2</b> for per-wedge "
|
||||
"texture coords, <b>ti</b> for face texture index, <b>vsel0,vsel1,vsel2</b> for vertex "
|
||||
"selection (1 yes, 0 no) "
|
||||
"<b>fi</b> for face index, <b>fr,fg,fb,fa</b> for face color, <b>fq</b> for face quality, "
|
||||
"<b>fnx,fny,fnz</b> for face normal, <b>fsel</b> face selection (1 yes, 0 no)."
|
||||
"All user defined <i>face scalar attributes</i> are available."
|
||||
"Point3 attribute are available as three variables with _x, _y, _z appended to the attribute name.<br><br>");
|
||||
"<ul><li>Per-face variables:<br>"
|
||||
"<b>fi</b> (face index), <b>fr,fg,fb,fa</b> (face color), <b>fq</b> (face quality), "
|
||||
"<b>fnx,fny,fnz</b> (face normal), <b>fsel</b> ( 1 if face is selected, 0 if not selected)."
|
||||
"</li><li>Per-vertex variables:<br>"
|
||||
"<b>x0,y0,z0</b> (first vertex position), <b>x1,y1,z1</b> (second vertex position),"
|
||||
"<b>x2,y2,z2</b> (third vertex position), "
|
||||
"<b>nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2</b> (vertex normals), <b>r0,g0,b0,a0 r1,g1,b1,a1 "
|
||||
"r2,g2,b2,a2</b> (vertex colors), <b>vi0, vi1, vi2</b> (vertex indices), "
|
||||
"<b>q0,q1,q2</b> (vertex quality), <b>wtu0,wtv0 wtu1,wtv1 wtu2,wtv2</b> (per-wedge texture coords), "
|
||||
"<b>ti</b> (face texture index), <b>vsel0,vsel1,vsel2</b> (1 if vertex is selected, 0 if not)."
|
||||
"</li><li>Bounding Box variables:<br>"
|
||||
"<b>xmin,ymin,zmin</b> (min coordinates), <b>xmax,ymax,zmax</b> (max coordinates), "
|
||||
"<b>xmid,ymid,zmid</b> (midpoint coordinates), <b>xdim,ydim,zdim</b> (dimensions), "
|
||||
"<b>bbdiag</b> (diagonal length)."
|
||||
"</li><li>User-defined attributes:<br>"
|
||||
"All user defined custom <i>face scalar attributes</i> are available. "
|
||||
"Point3 attribute are available as 3 variables with _x, _y, _z appended to the attribute name."
|
||||
"</li></ul>");
|
||||
|
||||
|
||||
// long string describing each filtering action
|
||||
QString FilterFunctionPlugin::filterInfo(ActionIDType filterId) const
|
||||
@ -694,6 +725,24 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
md.addNewMesh("", this->filterName(ID(filter)));
|
||||
MeshModel& m = *(md.mm());
|
||||
Q_UNUSED(cb);
|
||||
|
||||
//Set values to parser variables related to BBox
|
||||
const auto &bbox = m.cm.bbox;
|
||||
xmin = bbox.min.X();
|
||||
ymin = bbox.min.Y();
|
||||
zmin = bbox.min.Z();
|
||||
xmax = bbox.max.X();
|
||||
ymax = bbox.max.Y();
|
||||
zmax = bbox.max.Z();
|
||||
xdim = bbox.DimX();
|
||||
ydim = bbox.DimY();
|
||||
zdim = bbox.DimZ();
|
||||
bbdiag = bbox.Diag();
|
||||
auto bbCenter = bbox.Center();
|
||||
xmid = bbCenter.X();
|
||||
ymid = bbCenter.Y();
|
||||
zmid = bbCenter.Z();
|
||||
|
||||
switch (ID(filter)) {
|
||||
case FF_VERT_SELECTION: {
|
||||
std::string expr = par.getString("condSelect").toStdString();
|
||||
@ -701,7 +750,9 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
|
||||
// muparser initialization and explicitly define parser variables
|
||||
Parser p;
|
||||
|
||||
setPerVertexVariables(p, m.cm);
|
||||
setCustomFunctions(p);
|
||||
|
||||
// set expression inserted by user as string (required by muparser)
|
||||
p.SetExpr(wexpr);
|
||||
@ -747,7 +798,8 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
// muparser initialization and explicitly define parser variables
|
||||
Parser p;
|
||||
setPerFaceVariables(p, m.cm);
|
||||
|
||||
setCustomFunctions(p);
|
||||
|
||||
// set expression inserted by user as string (required by muparser)
|
||||
p.SetExpr(conversion::fromStringToWString(select.toStdString()));
|
||||
|
||||
@ -815,12 +867,16 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
// muparser initialization and explicitly define parser variables
|
||||
// function for x,y and z must use different parser and variables
|
||||
Parser p1, p2, p3, p4;
|
||||
|
||||
setPerVertexVariables(p1, m.cm);
|
||||
setPerVertexVariables(p2, m.cm);
|
||||
setPerVertexVariables(p3, m.cm);
|
||||
setPerVertexVariables(p4, m.cm);
|
||||
|
||||
setCustomFunctions(p1);
|
||||
setCustomFunctions(p2);
|
||||
setCustomFunctions(p3);
|
||||
setCustomFunctions(p4);
|
||||
|
||||
p1.SetExpr(conversion::fromStringToWString(func_x));
|
||||
p2.SetExpr(conversion::fromStringToWString(func_y));
|
||||
p3.SetExpr(conversion::fromStringToWString(func_z));
|
||||
@ -916,6 +972,9 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
Parser p;
|
||||
setPerVertexVariables(p, m.cm);
|
||||
|
||||
//Add rnd() and randInt() internal functions
|
||||
setCustomFunctions(p);
|
||||
|
||||
// set expression to calc with parser
|
||||
p.SetExpr(conversion::fromStringToWString(func_q));
|
||||
|
||||
@ -975,6 +1034,8 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
Parser pu, pv;
|
||||
setPerVertexVariables(pu, m.cm);
|
||||
setPerVertexVariables(pv, m.cm);
|
||||
setCustomFunctions(pu);
|
||||
setCustomFunctions(pv);
|
||||
|
||||
// set expression to calc with parser
|
||||
#ifdef _UNICODE
|
||||
@ -1033,6 +1094,12 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
setPerFaceVariables(pv1, m.cm);
|
||||
setPerFaceVariables(pu2, m.cm);
|
||||
setPerFaceVariables(pv2, m.cm);
|
||||
setCustomFunctions(pu0);
|
||||
setCustomFunctions(pv0);
|
||||
setCustomFunctions(pu1);
|
||||
setCustomFunctions(pv1);
|
||||
setCustomFunctions(pu2);
|
||||
setCustomFunctions(pv2);
|
||||
|
||||
// set expression to calc with parser
|
||||
pu0.SetExpr(conversion::fromStringToWString(func_u0));
|
||||
@ -1082,6 +1149,10 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
setPerFaceVariables(p_nx, m.cm);
|
||||
setPerFaceVariables(p_ny, m.cm);
|
||||
setPerFaceVariables(p_nz, m.cm);
|
||||
setCustomFunctions(p_nx);
|
||||
setCustomFunctions(p_ny);
|
||||
setCustomFunctions(p_nz);
|
||||
|
||||
p_nx.SetExpr(conversion::fromStringToWString(func_nx));
|
||||
p_ny.SetExpr(conversion::fromStringToWString(func_ny));
|
||||
p_nz.SetExpr(conversion::fromStringToWString(func_nz));
|
||||
@ -1154,6 +1225,10 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
setPerFaceVariables(p2, m.cm);
|
||||
setPerFaceVariables(p3, m.cm);
|
||||
setPerFaceVariables(p4, m.cm);
|
||||
setCustomFunctions(p1);
|
||||
setCustomFunctions(p2);
|
||||
setCustomFunctions(p3);
|
||||
setCustomFunctions(p4);
|
||||
|
||||
p1.SetExpr(conversion::fromStringToWString(func_r));
|
||||
p2.SetExpr(conversion::fromStringToWString(func_g));
|
||||
@ -1227,6 +1302,7 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
// muparser initialization and define custom variables
|
||||
Parser pf;
|
||||
setPerFaceVariables(pf, m.cm);
|
||||
setCustomFunctions(pf);
|
||||
|
||||
// set expression to calc with parser
|
||||
pf.SetExpr(conversion::fromStringToWString(func_q));
|
||||
@ -1286,6 +1362,7 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
|
||||
Parser p;
|
||||
setPerVertexVariables(p, m.cm);
|
||||
setCustomFunctions(p);
|
||||
|
||||
p.SetExpr(conversion::fromStringToWString(expr));
|
||||
|
||||
@ -1338,6 +1415,7 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
h = tri::Allocator<CMeshO>::AddPerFaceAttribute<Scalarm>(m.cm, name);
|
||||
Parser p;
|
||||
setPerFaceVariables(p, m.cm);
|
||||
setCustomFunctions(p);
|
||||
p.SetExpr(conversion::fromStringToWString(expr));
|
||||
|
||||
time_t start = clock();
|
||||
@ -1384,6 +1462,10 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
setPerVertexVariables(p_x, m.cm);
|
||||
setPerVertexVariables(p_y, m.cm);
|
||||
setPerVertexVariables(p_z, m.cm);
|
||||
setCustomFunctions(p_x);
|
||||
setCustomFunctions(p_y);
|
||||
setCustomFunctions(p_z);
|
||||
|
||||
p_x.SetExpr(conversion::fromStringToWString(x_expr));
|
||||
p_y.SetExpr(conversion::fromStringToWString(y_expr));
|
||||
p_z.SetExpr(conversion::fromStringToWString(z_expr));
|
||||
@ -1443,6 +1525,9 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
setPerFaceVariables(p_x, m.cm);
|
||||
setPerFaceVariables(p_y, m.cm);
|
||||
setPerFaceVariables(p_z, m.cm);
|
||||
setCustomFunctions(p_x);
|
||||
setCustomFunctions(p_y);
|
||||
setCustomFunctions(p_z);
|
||||
p_x.SetExpr(conversion::fromStringToWString(x_expr));
|
||||
p_y.SetExpr(conversion::fromStringToWString(y_expr));
|
||||
p_z.SetExpr(conversion::fromStringToWString(z_expr));
|
||||
@ -1524,6 +1609,8 @@ std::map<std::string, QVariant> FilterFunctionPlugin::applyFilter(
|
||||
|
||||
Parser p;
|
||||
double x, y, z;
|
||||
setCustomFunctions(p);
|
||||
|
||||
p.DefineVar(conversion::fromStringToWString("x"), &x);
|
||||
p.DefineVar(conversion::fromStringToWString("y"), &y);
|
||||
p.DefineVar(conversion::fromStringToWString("z"), &z);
|
||||
@ -1760,6 +1847,15 @@ void FilterFunctionPlugin::setAttributes(CMeshO::FaceIterator& fi, CMeshO& m)
|
||||
|
||||
}
|
||||
|
||||
// Generate a random double in [0.0, 1.0] interval
|
||||
double FilterFunctionPlugin::random()
|
||||
{
|
||||
std::random_device rd; // Seed for the random number engine
|
||||
std::mt19937 gen(rd()); // Mersenne Twister engine
|
||||
std::uniform_real_distribution<double> dis(0.0, 1.0);
|
||||
return dis(gen); // Generate a random double in [0.0, 1.0]
|
||||
}
|
||||
|
||||
// Function explicitly define parser variables to perform per-vertex filter action
|
||||
// x, y, z for vertex coord, nx, ny, nz for normal coord, r, g ,b for color
|
||||
// and q for quality
|
||||
@ -1782,6 +1878,24 @@ void FilterFunctionPlugin::setPerVertexVariables(Parser& p, CMeshO& m)
|
||||
p.DefineVar(conversion::fromStringToWString("ti"), &ti);
|
||||
p.DefineVar(conversion::fromStringToWString("vsel"), &vsel);
|
||||
|
||||
//Add tokens related to mesh bounding box
|
||||
p.DefineVar(conversion::fromStringToWString("xmin"), &xmin);
|
||||
p.DefineVar(conversion::fromStringToWString("ymin"), &ymin);
|
||||
p.DefineVar(conversion::fromStringToWString("zmin"), &zmin);
|
||||
p.DefineVar(conversion::fromStringToWString("xmax"), &xmax);
|
||||
p.DefineVar(conversion::fromStringToWString("ymax"), &ymax);
|
||||
p.DefineVar(conversion::fromStringToWString("zmax"), &zmax);
|
||||
p.DefineVar(conversion::fromStringToWString("bbdiag"), &bbdiag);
|
||||
p.DefineVar(conversion::fromStringToWString("xdim"), &xdim);
|
||||
p.DefineVar(conversion::fromStringToWString("ydim"), &ydim);
|
||||
p.DefineVar(conversion::fromStringToWString("zdim"), &zdim);
|
||||
p.DefineVar(conversion::fromStringToWString("xmid"), &xmid);
|
||||
p.DefineVar(conversion::fromStringToWString("ymid"), &ymid);
|
||||
p.DefineVar(conversion::fromStringToWString("zmid"), &zmid);
|
||||
|
||||
//Add function rnd()
|
||||
p.DefineFun("rnd", random);
|
||||
|
||||
// define var for user-defined attributes (if any exists)
|
||||
// if vector is empty, code won't be executed
|
||||
v_handlers.clear();
|
||||
@ -1910,6 +2024,24 @@ void FilterFunctionPlugin::setPerFaceVariables(Parser& p, CMeshO& m)
|
||||
p.DefineVar(conversion::fromStringToWString("vsel2"), &vsel2);
|
||||
p.DefineVar(conversion::fromStringToWString("fsel"), &fsel);
|
||||
|
||||
//Add tokens related to mesh bounding box
|
||||
p.DefineVar(conversion::fromStringToWString("xmin"), &xmin);
|
||||
p.DefineVar(conversion::fromStringToWString("ymin"), &ymin);
|
||||
p.DefineVar(conversion::fromStringToWString("zmin"), &zmin);
|
||||
p.DefineVar(conversion::fromStringToWString("xmax"), &xmax);
|
||||
p.DefineVar(conversion::fromStringToWString("ymax"), &ymax);
|
||||
p.DefineVar(conversion::fromStringToWString("zmax"), &zmax);
|
||||
p.DefineVar(conversion::fromStringToWString("bbdiag"), &bbdiag);
|
||||
p.DefineVar(conversion::fromStringToWString("xdim"), &xdim);
|
||||
p.DefineVar(conversion::fromStringToWString("ydim"), &ydim);
|
||||
p.DefineVar(conversion::fromStringToWString("zdim"), &zdim);
|
||||
p.DefineVar(conversion::fromStringToWString("xmid"), &xmid);
|
||||
p.DefineVar(conversion::fromStringToWString("ymid"), &ymid);
|
||||
p.DefineVar(conversion::fromStringToWString("zmid"), &zmid);
|
||||
|
||||
//Add function rnd()
|
||||
p.DefineFun("rnd", random);
|
||||
|
||||
// define var for user-defined attributes (if any exists)
|
||||
// if vector is empty, code won't be executed
|
||||
f_handlers.clear();
|
||||
|
||||
@ -44,6 +44,10 @@ protected:
|
||||
vsel0, vsel1, vsel2;
|
||||
double fr, fg, fb, fa, fnx, fny, fnz, fq, fsel;
|
||||
double v, f, v0i, v1i, v2i, ti;
|
||||
|
||||
//Bounding Box of the mesh
|
||||
double xmin, ymin, zmin, xmax, ymax, zmax, xdim, ydim, zdim, bbdiag, xmid, ymid, zmid;
|
||||
|
||||
std::vector<std::string> v_attrNames; // names of the <float> per vertex attributes
|
||||
std::vector<double> v_attrValue; // values of the <Scalarm> per vertex attributes
|
||||
std::vector<std::string> v3_attrNames; // names of the <Point3f> per vertex attributes There are
|
||||
@ -62,6 +66,9 @@ protected:
|
||||
|
||||
QString errorMsg;
|
||||
|
||||
// Generate a random double in [0.0, 1.0] interval
|
||||
static double random();
|
||||
|
||||
public:
|
||||
enum {
|
||||
FF_VERT_SELECTION,
|
||||
|
||||
@ -44,7 +44,8 @@ FilterGeodesic::FilterGeodesic()
|
||||
typeList = {
|
||||
FP_QUALITY_BORDER_GEODESIC,
|
||||
FP_QUALITY_POINT_GEODESIC,
|
||||
FP_QUALITY_SELECTED_GEODESIC
|
||||
FP_QUALITY_SELECTED_GEODESIC,
|
||||
FP_QUALITY_SELECTED_GEODESIC_HEAT
|
||||
};
|
||||
|
||||
for(ActionIDType tt : types())
|
||||
@ -67,6 +68,8 @@ QString FilterGeodesic::filterName(ActionIDType filter) const
|
||||
return QString("Colorize by geodesic distance from a given point");
|
||||
case FP_QUALITY_SELECTED_GEODESIC:
|
||||
return QString("Colorize by geodesic distance from the selected points");
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT:
|
||||
return QString("Colorize by approximated geodesic distance from the selected points");
|
||||
default: assert(0); return QString();
|
||||
}
|
||||
}
|
||||
@ -79,6 +82,8 @@ QString FilterGeodesic::pythonFilterName(ActionIDType f) const
|
||||
return QString("compute_scalar_by_geodesic_distance_from_given_point_per_vertex");
|
||||
case FP_QUALITY_SELECTED_GEODESIC:
|
||||
return QString("compute_scalar_by_geodesic_distance_from_selection_per_vertex");
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT:
|
||||
return QString("compute_scalar_by_heat_geodesic_distance_from_selection_per_vertex");
|
||||
default: assert(0); return QString();
|
||||
}
|
||||
}
|
||||
@ -87,9 +92,10 @@ QString FilterGeodesic::filterInfo(ActionIDType filterId) const
|
||||
{
|
||||
switch(filterId)
|
||||
{
|
||||
case FP_QUALITY_BORDER_GEODESIC : return tr("Store in the quality field the geodesic distance from borders and color the mesh accordingly.");
|
||||
case FP_QUALITY_POINT_GEODESIC : return tr("Store in the quality field the geodesic distance from a given point on the mesh surface and color the mesh accordingly.");
|
||||
case FP_QUALITY_SELECTED_GEODESIC : return tr("Store in the quality field the geodesic distance from the selected points on the mesh surface and color the mesh accordingly.");
|
||||
case FP_QUALITY_BORDER_GEODESIC : return tr("Store in the quality field the geodesic distance from borders and color the mesh accordingly.");
|
||||
case FP_QUALITY_POINT_GEODESIC : return tr("Store in the quality field the geodesic distance from a given point on the mesh surface and color the mesh accordingly.");
|
||||
case FP_QUALITY_SELECTED_GEODESIC : return tr("Store in the quality field the geodesic distance from the selected points on the mesh surface and color the mesh accordingly.");
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT : return tr("Store in the quality field the approximated geodesic distance, computed via heat method (Crane et al.), from the selected points on the mesh surface and color the mesh accordingly. As this implementation does not use intrinsic triangulation it is very sensitive to trinagulation. First run takes longer as factorization has to be build. ");
|
||||
default : assert(0);
|
||||
}
|
||||
return QString("error!");
|
||||
@ -99,9 +105,10 @@ FilterGeodesic::FilterClass FilterGeodesic::getClass(const QAction *a) const
|
||||
{
|
||||
switch(ID(a))
|
||||
{
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
case FP_QUALITY_POINT_GEODESIC : return FilterGeodesic::FilterClass(FilterPlugin::VertexColoring + FilterPlugin::Quality);
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
case FP_QUALITY_POINT_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT : return FilterGeodesic::FilterClass(FilterPlugin::VertexColoring + FilterPlugin::Quality);
|
||||
default : assert(0);
|
||||
}
|
||||
return FilterPlugin::Generic;
|
||||
@ -111,15 +118,16 @@ int FilterGeodesic::getRequirements(const QAction *action)
|
||||
{
|
||||
switch(ID(action))
|
||||
{
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC:
|
||||
case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTFACETOPO;
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTFACETOPO;
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT : return MeshModel::MM_VERTFACETOPO + MeshModel::MM_FACEFACETOPO;
|
||||
default: assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<std::string, QVariant> FilterGeodesic::applyFilter(const QAction *filter, const RichParameterList & par, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos * /*cb*/)
|
||||
std::map<std::string, QVariant> FilterGeodesic::applyFilter(const QAction *filter, const RichParameterList & par, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos *cb)
|
||||
{
|
||||
MeshModel &m=*(md.mm());
|
||||
CMeshO::VertexIterator vi;
|
||||
@ -236,7 +244,60 @@ std::map<std::string, QVariant> FilterGeodesic::applyFilter(const QAction *filte
|
||||
else
|
||||
log("Warning: no vertices are selected! aborting geodesic computation.");
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT:
|
||||
{
|
||||
m.updateDataMask(MeshModel::MM_FACEFACETOPO);
|
||||
m.updateDataMask(MeshModel::MM_VERTFACETOPO);
|
||||
m.updateDataMask(MeshModel::MM_FACEQUALITY);
|
||||
m.updateDataMask(MeshModel::MM_FACENORMAL);
|
||||
m.updateDataMask(MeshModel::MM_VERTQUALITY);
|
||||
m.updateDataMask(MeshModel::MM_VERTCOLOR);
|
||||
|
||||
std::vector<CMeshO::VertexPointer> seedVec;
|
||||
ForEachVertex(m.cm, [&seedVec] (CMeshO::VertexType & v) {
|
||||
if (v.IsS()) seedVec.push_back(&v);
|
||||
});
|
||||
|
||||
float param_m = par.getFloat("m");
|
||||
|
||||
if (seedVec.size() > 0){
|
||||
// cache factorizations to reduce runtime on successive computations
|
||||
std::pair<float, tri::GeodesicHeat<CMeshO>::GeodesicHeatCache> cache;
|
||||
if (!vcg::tri::HasPerMeshAttribute(m.cm, "GeodesicHeatCache")){
|
||||
cb(20, "Building Cache: Computing Factorizations...");
|
||||
cache = std::make_pair(param_m, tri::GeodesicHeat<CMeshO>::BuildCache(m.cm, param_m));
|
||||
// save cache for next compute
|
||||
auto GeodesicHeatCacheHandle = tri::Allocator<CMeshO>::GetPerMeshAttribute<std::pair<float, tri::GeodesicHeat<CMeshO>::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache"));
|
||||
GeodesicHeatCacheHandle() = cache;
|
||||
}
|
||||
else {
|
||||
cb(10, "Recovering Cache...");
|
||||
// recover cache
|
||||
auto GeodesicHeatCacheHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<std::pair<float, tri::GeodesicHeat<CMeshO>::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache"));
|
||||
// if m has changed rebuild everything
|
||||
if (std::get<0>(GeodesicHeatCacheHandle()) != param_m){
|
||||
cb(20, "Parameter Changed: Rebuilding Factorizations...");
|
||||
GeodesicHeatCacheHandle() = std::make_pair(param_m, tri::GeodesicHeat<CMeshO>::BuildCache(m.cm, param_m));
|
||||
}
|
||||
cache = GeodesicHeatCacheHandle();
|
||||
}
|
||||
cb(80, "Computing Geodesic Distance...");
|
||||
|
||||
if (tri::GeodesicHeat<CMeshO>::ComputeFromCache(m.cm, seedVec, std::get<1>(cache))){
|
||||
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm);
|
||||
}
|
||||
else{
|
||||
log("Warning: heat method has failed. The mesh is most likely badly conditioned (e.g. angles ~ 0deg) or has disconnected components");
|
||||
// delete cache as its most likely useless after failure
|
||||
auto GeodesicHeatCacheHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<std::pair<float, tri::GeodesicHeat<CMeshO>::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache"));
|
||||
tri::Allocator<CMeshO>::DeletePerMeshAttribute<std::pair<float, tri::GeodesicHeat<CMeshO>::GeodesicHeatCache>>(m.cm, GeodesicHeatCacheHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
log("Warning: no vertices are selected! aborting geodesic computation.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wrongActionCalled(filter);
|
||||
break;
|
||||
@ -255,7 +316,10 @@ RichParameterList FilterGeodesic::initParameterList(const QAction *action, const
|
||||
break;
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
parlst.addParam(RichPercentage("maxDistance",m.cm.bbox.Diag(),0,m.cm.bbox.Diag()*2,"Max Distance","If not zero it indicates a cut off value to be used during geodesic distance computation."));
|
||||
break;
|
||||
break;
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT :
|
||||
parlst.addParam(RichFloat("m", 1.0, tr("Euler Step"), tr("Multiplier used in backward Euler timestep. Changing this value will reset the cache.")));
|
||||
break;
|
||||
default: break; // do not add any parameter for the other filters
|
||||
}
|
||||
return parlst;
|
||||
@ -265,10 +329,11 @@ int FilterGeodesic::postCondition(const QAction * filter) const
|
||||
{
|
||||
switch (ID(filter))
|
||||
{
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY;
|
||||
default : return MeshModel::MM_ALL;
|
||||
case FP_QUALITY_BORDER_GEODESIC :
|
||||
case FP_QUALITY_SELECTED_GEODESIC :
|
||||
case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY;
|
||||
case FP_QUALITY_SELECTED_GEODESIC_HEAT : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY + MeshModel::MM_FACEQUALITY;
|
||||
default : return MeshModel::MM_ALL;
|
||||
}
|
||||
}
|
||||
MESHLAB_PLUGIN_NAME_EXPORTER(FilterGeodesic)
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <QObject>
|
||||
#include <common/plugins/interfaces/filter_plugin.h>
|
||||
#include <vcg/complex/algorithms/geodesic.h>
|
||||
#include <vcg/complex/algorithms/geodesic_heat.h>
|
||||
|
||||
|
||||
class FilterGeodesic : public QObject, public FilterPlugin
|
||||
@ -42,7 +43,8 @@ class FilterGeodesic : public QObject, public FilterPlugin
|
||||
enum {
|
||||
FP_QUALITY_BORDER_GEODESIC,
|
||||
FP_QUALITY_POINT_GEODESIC,
|
||||
FP_QUALITY_SELECTED_GEODESIC
|
||||
FP_QUALITY_SELECTED_GEODESIC,
|
||||
FP_QUALITY_SELECTED_GEODESIC_HEAT
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <vcg/complex/algorithms/smooth.h>
|
||||
#include <vcg/complex/algorithms/create/plymc/plymc.h>
|
||||
#include <vcg/complex/algorithms/create/plymc/simplemeshprovider.h>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
using namespace vcg;
|
||||
@ -142,13 +143,21 @@ std::map<std::string, QVariant> PlyMCPlugin::applyFilter(
|
||||
case FP_PLYMC:
|
||||
{
|
||||
srand(time(NULL));
|
||||
|
||||
//check if folder is writable
|
||||
QTemporaryFile file("./_tmp_XXXXXX.tmp");
|
||||
if (!file.open())
|
||||
{
|
||||
log("ERROR - current folder is not writable. VCG Merging needs to save intermediate files in the current working folder. Project and meshes must be in a write-enabled folder. Please save your data in a suitable folder before applying.");
|
||||
throw MLException("current folder is not writable.<br> VCG Merging needs to save intermediate files in the current working folder.<br> Project and meshes must be in a write-enabled folder.<br> Please save your data in a suitable folder before applying.");
|
||||
|
||||
QDir currDir = QDir::current();
|
||||
|
||||
//Using tmp dir
|
||||
QTemporaryDir tmpdir;
|
||||
QTemporaryFile file(tmpdir.path());
|
||||
if (!file.open()) {
|
||||
log("ERROR - tmp folder is not writable. VCG Merging needs to save intermediate files "
|
||||
"in the tmp folder.");
|
||||
throw MLException(
|
||||
"tmp folder is not writable.<br> VCG Merging needs to save intermediate files in "
|
||||
"the tmp folder.");
|
||||
}
|
||||
else {
|
||||
QDir::setCurrent(tmpdir.path());
|
||||
}
|
||||
|
||||
tri::PlyMC<SMesh,SimpleMeshProvider<SMesh> > pmc;
|
||||
@ -170,10 +179,8 @@ std::map<std::string, QVariant> PlyMCPlugin::applyFilter(
|
||||
p.FullyPreprocessedFlag=true;
|
||||
p.MergeColor=p.VertSplatFlag=par.getBool("mergeColor");
|
||||
p.SimplificationFlag = par.getBool("simplification");
|
||||
for(MeshModel& mm: md.meshIterator())
|
||||
{
|
||||
if(mm.isVisible())
|
||||
{
|
||||
for(MeshModel& mm: md.meshIterator()) {
|
||||
if(mm.isVisible()) {
|
||||
SMesh sm;
|
||||
mm.updateDataMask(MeshModel::MM_FACEQUALITY);
|
||||
tri::Append<SMesh,CMeshO>::Mesh(sm, mm.cm/*,false,p.VertSplatFlag*/); // note the last parameter of the append to prevent removal of unreferenced vertices...
|
||||
@ -189,8 +196,7 @@ std::map<std::string, QVariant> PlyMCPlugin::applyFilter(
|
||||
QString mshTmpPath=QString("__TMP")+QString(mm.shortName())+QString(".vmi");
|
||||
qDebug("Saving tmp file %s",qUtf8Printable(mshTmpPath));
|
||||
int retVal = tri::io::ExporterVMI<SMesh>::Save(sm,qUtf8Printable(mshTmpPath) );
|
||||
if(retVal!=0)
|
||||
{
|
||||
if(retVal!=0) {
|
||||
qDebug("Failed to write vmi temp file %s",qUtf8Printable(mshTmpPath));
|
||||
|
||||
log("ERROR - Failed to write vmi temp file %s", qUtf8Printable(mshTmpPath));
|
||||
@ -201,14 +207,12 @@ std::map<std::string, QVariant> PlyMCPlugin::applyFilter(
|
||||
}
|
||||
}
|
||||
|
||||
if(pmc.Process(cb)==false)
|
||||
{
|
||||
if(pmc.Process(cb)==false) {
|
||||
throw MLException(pmc.errorMessage.c_str());
|
||||
}
|
||||
|
||||
|
||||
if(par.getBool("openResult"))
|
||||
{
|
||||
if(par.getBool("openResult")) {
|
||||
for(size_t i=0;i<p.OutNameVec.size();++i)
|
||||
{std::string name;
|
||||
if(!p.SimplificationFlag) name = p.OutNameVec[i].c_str();
|
||||
@ -225,6 +229,8 @@ std::map<std::string, QVariant> PlyMCPlugin::applyFilter(
|
||||
|
||||
for(int i=0;i<pmc.MP.size();++i)
|
||||
QFile::remove(pmc.MP.MeshName(i).c_str());
|
||||
|
||||
QDir::setCurrent(currDir.path());
|
||||
} break;
|
||||
case FP_MC_SIMPLIFY:
|
||||
{
|
||||
|
||||
@ -296,19 +296,19 @@ void U3DIOPlugin::saveLatex(const QString& file,const vcg::tri::io::u3dparameter
|
||||
std::string u3d_final =
|
||||
vcg::tri::io::QtUtilityFunctions::fileNameFromTrimmedPath(file_trim).toStdString();
|
||||
latex.write(0,"\\documentclass[a4paper]{article}");
|
||||
latex.write(0,"\\usepackage[3D]{movie15}");
|
||||
latex.write(0,"\\usepackage[3Dmenu]{media9}");
|
||||
latex.write(0,"\\usepackage{hyperref}");
|
||||
latex.write(0,"\\usepackage[UKenglish]{babel}");
|
||||
latex.write(0,"\\begin{document}");
|
||||
latex.write(0,"\\includemovie[");
|
||||
latex.write(1,"poster,");
|
||||
latex.write(1,"toolbar, %same as `controls\'");
|
||||
latex.write(0,"\\includemedia[");
|
||||
latex.write(1,"width=\\linewidth,height=\\linewidth,");
|
||||
latex.write(1,"3Dmenu,'");
|
||||
|
||||
|
||||
QString u3d_text = QString::fromStdString(u3d_final);
|
||||
substituteChar(u3d_text,QChar('_'),QString(""));
|
||||
latex.write(1,"label=" + u3d_text.toStdString() + ",");
|
||||
latex.write(1,"text=(" + u3d_text.toStdString() + "),");
|
||||
latex.write(1,"activate=pageopen,");
|
||||
std::string cam_string;
|
||||
typename vcg::tri::io::u3dparametersclasses::Movie15Parameters<CMeshO>::CameraParameters* cam = mov_par._campar;
|
||||
if (cam != NULL) {
|
||||
@ -319,8 +319,8 @@ void U3DIOPlugin::saveLatex(const QString& file,const vcg::tri::io::u3dparameter
|
||||
", 3Dcoo=" + TextUtility::nmbToStr(-cam->_obj_pos.X()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Z()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Y()) + ",";
|
||||
latex.write(1,cam_string);
|
||||
}
|
||||
latex.write(1,"3Dlights=CAD,");
|
||||
latex.write(0,"]{\\linewidth}{\\linewidth}{" + u3d_final + "}");
|
||||
latex.write(1,"3Dlights=CAD");
|
||||
latex.write(0,"]{}{" + u3d_final + "}");
|
||||
latex.write(0,"\\end{document}");
|
||||
}
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit d3822ec0cd1161de2223ddc4f126c413d398dad1
|
||||
Subproject commit 97adf94662ed4e54752c456d6ebfa97d7bf92ebd
|
||||
Loading…
x
Reference in New Issue
Block a user