Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed363da1f6 | ||
|
|
15bd0e0996 | ||
|
|
8235ccb3d0 | ||
|
|
61639328f9 | ||
|
|
8ca734ee17 | ||
|
|
1bfaa60e32 | ||
|
|
67c8d6a141 | ||
|
|
971d190108 | ||
|
|
b2e8d0b3d3 | ||
|
|
ae3df06258 | ||
|
|
75577c62d7 | ||
|
|
8895c712b6 | ||
|
|
7f852d8aee | ||
|
|
d3dd83f11b | ||
|
|
5977205363 | ||
|
|
954cd99196 | ||
|
|
883d0a5028 | ||
|
|
036fc21668 | ||
|
|
8035584024 | ||
|
|
72f08a45b8 | ||
|
|
a1e026fbe6 | ||
|
|
b672900456 | ||
|
|
e9fc2a82eb | ||
|
|
0c831a3fe9 | ||
|
|
956c94dfad | ||
|
|
8825f6f94a | ||
|
|
e4d513a0b7 | ||
|
|
5066b5d253 | ||
|
|
99bc7bddb6 | ||
|
|
14da3a4a9a | ||
|
|
ee2599de1a | ||
|
|
ba47646bc5 | ||
|
|
8ce9abcfc6 | ||
|
|
0bfa95b9d9 | ||
|
|
10200efa2b | ||
|
|
af18599ef7 | ||
|
|
c722b46cbd | ||
|
|
2921ffaff6 | ||
|
|
76370d4525 | ||
|
|
0787113a1b | ||
|
|
3f7895d172 | ||
|
|
ef78023af4 | ||
|
|
242a4485af | ||
|
|
4ffc570482 | ||
|
|
4d66545557 | ||
|
|
628375d4d2 | ||
|
|
340521757c | ||
|
|
76b8ca17d8 | ||
|
|
1ef33b03a2 | ||
|
|
0d1d133330 | ||
|
|
1fe4eb190f | ||
|
|
65aa93e9ef | ||
|
|
7cb42ce972 | ||
|
|
c0c396c237 | ||
|
|
7dc2b11c2a | ||
|
|
3f442b54f3 | ||
|
|
96c8ea4931 | ||
|
|
928cbe67bb | ||
|
|
9a149ece72 | ||
|
|
76ae819489 | ||
|
|
66ec792368 | ||
|
|
2726464472 | ||
|
|
31d419e2c0 | ||
|
|
9e10c1b534 | ||
|
|
4e739bc528 | ||
|
|
d3510ceeba | ||
|
|
41b4a5e62e | ||
|
|
2de5e29fc9 | ||
|
|
93cba2e044 | ||
|
|
a38371d231 | ||
|
|
5e20808faa | ||
|
|
714658b8d7 | ||
|
|
414740aa38 | ||
|
|
0cdc451a80 | ||
|
|
56eee0e3a4 | ||
|
|
5b534bff4c | ||
|
|
12b904a5b8 | ||
|
|
bcddf01d77 | ||
|
|
b0eb3db0aa | ||
|
|
409aee509d | ||
|
|
0c2b5cec70 | ||
|
|
075e95bfd2 | ||
|
|
3e35dc3a76 | ||
|
|
7b6ebdc3ea | ||
|
|
c192e28084 | ||
|
|
59251ca327 | ||
|
|
2a47253152 | ||
|
|
ef42f203ad | ||
|
|
e0849c88da | ||
|
|
c415f21858 | ||
|
|
4125afe80f | ||
|
|
f16ee6d7c5 | ||
|
|
8847026227 | ||
|
|
a6423836aa | ||
|
|
03653319d1 | ||
|
|
f12ffbd24e | ||
|
|
28801efb8b | ||
|
|
4db3a4c521 | ||
|
|
85ffda7ef4 | ||
|
|
2e66247d99 | ||
|
|
5f428b210e | ||
|
|
7aed747cd7 | ||
|
|
3ef2e16408 | ||
|
|
45acb3a583 | ||
|
|
42883bb57a | ||
|
|
c7c906c204 | ||
|
|
dd44506bcc | ||
|
|
4f83e01386 | ||
|
|
e2a7dc74dd | ||
|
|
8c5e9bd9bd | ||
|
|
855f60f9f6 | ||
|
|
bb730dec7d | ||
|
|
cec9df42aa | ||
|
|
2b666475ec | ||
|
|
fd8ee231b1 | ||
|
|
66696c2222 | ||
|
|
c47b26d73a | ||
|
|
db2419a6e3 | ||
|
|
2ceac853c3 | ||
|
|
f6c1f0bea1 | ||
|
|
1a42b39c93 | ||
|
|
a54d558f82 | ||
|
|
ef81faeac2 | ||
|
|
7117af68b5 | ||
|
|
5b13a5c490 | ||
|
|
c314bf9182 | ||
|
|
58f16f00e7 | ||
|
|
621f31e10e | ||
|
|
209b81e56c | ||
|
|
92f2e20fa5 | ||
|
|
9cdf351f6b | ||
|
|
7fba338427 | ||
|
|
eb6ffec8d5 | ||
|
|
edf08926c5 | ||
|
|
b3fce1689c | ||
|
|
de3749fc55 | ||
|
|
a9c3b6d50a | ||
|
|
18a1eaf38c | ||
|
|
075f884f5f | ||
|
|
28f59dfe2f | ||
|
|
2256dd7264 | ||
|
|
eaa2d52f4e | ||
|
|
418d98b02e | ||
|
|
e8ca66fb7c | ||
|
|
90ed035285 | ||
|
|
7f305a8532 | ||
|
|
87d401b82b | ||
|
|
dc1d3bb46c | ||
|
|
da3bd928dd | ||
|
|
86128972f6 | ||
|
|
dfbc3ee1c1 | ||
|
|
576529d8d9 | ||
|
|
792c814200 | ||
|
|
4a3ce8d896 | ||
|
|
dde2f93dd7 | ||
|
|
83db1d2f19 | ||
|
|
94dac679eb | ||
|
|
e2e4926241 | ||
|
|
8571d5f3a2 | ||
|
|
7c249cb5e2 |
+4
-7
@@ -5,9 +5,7 @@ clone_folder: C:\projects\libigl
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- alecjacobson
|
||||
- cmake
|
||||
- cgal
|
||||
- dev
|
||||
environment:
|
||||
BOOST_ROOT: C:/Libraries/boost_1_65_1
|
||||
install:
|
||||
@@ -31,11 +29,10 @@ build_script:
|
||||
# - cd ../tutorial
|
||||
# - ${PYTHON} 101_FileIO.py
|
||||
# - cd ../../
|
||||
# Tutorials
|
||||
- cd tutorial
|
||||
# Tutorials and tests
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DLIBIGL_USE_STATIC_LIBRARY=ON -G "Visual Studio 15 2017 Win64" ../
|
||||
- cmake -DLIBIGL_BUILD_TESTS=OFF -DLIBIGL_BUILD_TUTORIALS=ON -DLIBIGL_BUILD_PYTHON=OFF -G "Visual Studio 15 2017 Win64" ../
|
||||
- set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
- set MSBuildOptions=/v:m /p:Configuration=Debug /logger:%MSBuildLogger%
|
||||
- msbuild %MSBuildOptions% libigl_tutorials.sln
|
||||
- msbuild %MSBuildOptions% libigl.sln
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[Describe your issue]
|
||||
|
||||
#### Check all that apply (change to `[x]`)
|
||||
- [ ] Windows
|
||||
- [ ] Mac OS X
|
||||
- [ ] Linux
|
||||
|
||||
See <https://libigl.github.io/CONTRIBUTING/#bugreport> for more tips.
|
||||
@@ -0,0 +1,8 @@
|
||||
[Describe your changes and what you've already done to test it.]
|
||||
|
||||
#### Check all that apply (change to `[x]`)
|
||||
- [ ] All changes meet [libigl style-guidelines](https://libigl.github.io/style-guidelines/).
|
||||
- [ ] Adds new .cpp file.
|
||||
- [ ] Adds corresponding unit test.
|
||||
- [ ] Adds corresponding python binding.
|
||||
- [ ] This is a minor change.
|
||||
+76
-87
@@ -1,110 +1,99 @@
|
||||
# use glob syntax.
|
||||
syntax: glob
|
||||
scripts/change_name.sh
|
||||
*.a
|
||||
*.dylib
|
||||
*.egg-info/
|
||||
*.exe
|
||||
*.ilk
|
||||
*.log
|
||||
*.o
|
||||
*.opensdf
|
||||
*.orig
|
||||
*.pdb
|
||||
*.psess
|
||||
*.pyc
|
||||
*.sdf
|
||||
*.so
|
||||
*.so.[0123456789]
|
||||
*.so.[0123456789].[0123456789]
|
||||
*.o
|
||||
*.a
|
||||
*.dylib
|
||||
*~
|
||||
*CMakeFiles*
|
||||
example
|
||||
examples/bbw/bbw_demo_selfcontained/*
|
||||
examples/bbw/bbw_demo_selfcontained.zip
|
||||
examples/quicklook-mesh/Mesh.qlgenerator/*
|
||||
examples/*/*.mexmaci64
|
||||
examples/*/*.rbr
|
||||
example_static
|
||||
example_header_only
|
||||
example1
|
||||
external/yimg/.git*
|
||||
external/tinyxml2/CMakeFiles*
|
||||
external/tinyxml2/CMakeCache.txt
|
||||
external/tinyxml2/cmake_install.cmake
|
||||
external/tinyxml2/Makefile
|
||||
external/embree/build/*
|
||||
external/embree/bin/*
|
||||
external/embree/bin
|
||||
external/embree/doc/html/*
|
||||
external/embree/doc/latex/*
|
||||
external/gmp
|
||||
external/mpfr
|
||||
external/boost
|
||||
external/.cache
|
||||
external/build
|
||||
.DS_Store
|
||||
libigl.zip
|
||||
*tags
|
||||
*.exe
|
||||
*.pdb
|
||||
*.sdf
|
||||
*.suo
|
||||
*.ilk
|
||||
*.log
|
||||
*.swo
|
||||
*.swp
|
||||
*.tlog
|
||||
Debug/
|
||||
Release/
|
||||
*.orig
|
||||
*.user
|
||||
*.vsp
|
||||
*.opensdf
|
||||
*.psess
|
||||
*.swp
|
||||
*.swo
|
||||
documentation/*.aux
|
||||
documentation/*.out
|
||||
documentation/*.log
|
||||
*CMakeFiles*
|
||||
*buildXcode*
|
||||
*tags
|
||||
*~
|
||||
.DS_Store
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
/external
|
||||
Debug/
|
||||
README.html
|
||||
Release/
|
||||
Untitled.ipynb
|
||||
build
|
||||
doc.html
|
||||
documentation/*.aux
|
||||
documentation/*.log
|
||||
documentation/*.out
|
||||
example
|
||||
example1
|
||||
example_header_only
|
||||
example_static
|
||||
examples/*/*.mexmaci64
|
||||
examples/*/*.rbr
|
||||
examples/bbw/bbw_demo
|
||||
external/medit/rebar.rbr
|
||||
examples/bbw/bbw_demo_selfcontained.zip
|
||||
examples/bbw/bbw_demo_selfcontained/*
|
||||
examples/bbw/examples/*-volume.dmat
|
||||
examples/bbw/examples/*-volume.mesh
|
||||
examples/upright/upright
|
||||
examples/principal_curvature/curvature
|
||||
examples/quicklook-mesh/Mesh.qlgenerator/*
|
||||
examples/upright/upright
|
||||
external/MeshFix/meshfix
|
||||
external/embree/build/*
|
||||
external/glew/build
|
||||
external/glfw/build
|
||||
external/libpng/build
|
||||
external/medit/rebar.rbr
|
||||
external/tetgen/tetgen
|
||||
external/tinyxml2/build
|
||||
external/tinyxml2/test
|
||||
external/tinyxml2/tinyxml2.pc
|
||||
external/yimg/showpng
|
||||
README.html
|
||||
tutorial/readme.html
|
||||
tutorial/*/build/*
|
||||
tutorial/*/Makefile
|
||||
external/glew/build
|
||||
external/glfw/build
|
||||
*buildXcode*
|
||||
tutorial/build*
|
||||
tutorial/*/*.mexmaci64
|
||||
external/libpng/build
|
||||
external/tinyxml2/build
|
||||
optional/build
|
||||
iglhelpers.pyc
|
||||
lib
|
||||
libigl.zip
|
||||
optional/build
|
||||
python/.idea
|
||||
python/.ipynb_checkpoints
|
||||
python/__pycache__
|
||||
python/build
|
||||
python/build2
|
||||
python/build3
|
||||
python/build4
|
||||
python/builddebug
|
||||
python/buildstatic
|
||||
python/py_igl/todo
|
||||
python/py_igl/todo
|
||||
python/scripts/generated
|
||||
scripts/change_name.sh
|
||||
site/
|
||||
syntax: glob
|
||||
tests/bin
|
||||
tests/build
|
||||
tests/data
|
||||
tutorial/*/*.mexmaci64
|
||||
tutorial/*/Makefile
|
||||
tutorial/*/build/*
|
||||
tutorial/.idea
|
||||
tutorial/XXX_test/CMakeLists.txt
|
||||
tutorial/XXX_test/main.cpp
|
||||
python/py_igl/todo
|
||||
python/build
|
||||
python/.idea
|
||||
untitled
|
||||
Untitled.ipynb
|
||||
python/.ipynb_checkpoints
|
||||
python/py_igl/todo
|
||||
python/__pycache__
|
||||
iglhelpers.pyc
|
||||
python/build2
|
||||
tests/build
|
||||
tests/bin
|
||||
python/build3
|
||||
*.pyc
|
||||
python/build4
|
||||
python/scripts/generated
|
||||
python/builddebug
|
||||
tutorial/.idea
|
||||
python/buildstatic
|
||||
tutorial/build
|
||||
tutorial/cmake-build-debug
|
||||
.vscode/
|
||||
.idea/
|
||||
site/
|
||||
*.egg-info/
|
||||
.vs/
|
||||
tutorial/data
|
||||
tutorial/readme.html
|
||||
untitled
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
[submodule "external/embree"]
|
||||
path = external/embree
|
||||
url = https://github.com/embree/embree.git
|
||||
[submodule "external/cgal"]
|
||||
path = external/cgal
|
||||
url = https://github.com/CGAL/cgal.git
|
||||
[submodule "external/tetgen"]
|
||||
path = external/tetgen
|
||||
url = https://github.com/libigl/tetgen.git
|
||||
[submodule "external/triangle"]
|
||||
path = external/triangle
|
||||
url = https://github.com/libigl/triangle.git
|
||||
[submodule "external/tinyxml2"]
|
||||
path = external/tinyxml2
|
||||
url = https://github.com/leethomason/tinyxml2.git
|
||||
[submodule "external/CoMISo"]
|
||||
path = external/CoMISo
|
||||
url = https://github.com/libigl/CoMISo.git
|
||||
[submodule "external/cork"]
|
||||
path = external/cork
|
||||
url = https://github.com/libigl/cork.git
|
||||
[submodule "external/imgui"]
|
||||
path = external/imgui/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
[submodule "external/glfw"]
|
||||
path = external/glfw
|
||||
url = https://github.com/glfw/glfw.git
|
||||
[submodule "external/eigen"]
|
||||
path = external/eigen
|
||||
url = https://github.com/eigenteam/eigen-git-mirror.git
|
||||
[submodule "external/pybind11"]
|
||||
path = external/pybind11
|
||||
url = https://github.com/pybind/pybind11
|
||||
+5
-10
@@ -57,17 +57,12 @@ install:
|
||||
- ccache -V && ccache --show-stats && ccache --zero-stats
|
||||
|
||||
script:
|
||||
# Python bindings
|
||||
- cd python
|
||||
- ${PYTHON} setup.py develop --user -- -DCMAKE_BUILD_TYPE=${CONFIG} -DLIBIGL_WITH_EMBREE=OFF -DLIBIGL_USE_STATIC_LIBRARY=ON -DCHECK_UNDEFINED=${CHECK_UNDEFINED}
|
||||
- cd tutorial
|
||||
- ${PYTHON} 101_FileIO.py
|
||||
- cd ../../
|
||||
- rm -rf python/build
|
||||
# Tutorials
|
||||
- cd tutorial
|
||||
# Tutorials and tests
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=$CONFIG -DLIBIGL_USE_STATIC_LIBRARY=ON ../
|
||||
- cmake -DCMAKE_BUILD_TYPE=$CONFIG -DLIBIGL_BUILD_TESTS=ON -DLIBIGL_BUILD_TUTORIALS=ON ../
|
||||
- make -j 2
|
||||
- ctest --verbose
|
||||
- ccache --show-stats
|
||||
- cd ../
|
||||
- rm -rf build
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(libigl)
|
||||
|
||||
# Detects whether this is a top-level project
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
set(LIBIGL_TOPLEVEL_PROJECT ON)
|
||||
else()
|
||||
set(LIBIGL_TOPLEVEL_PROJECT OFF)
|
||||
endif()
|
||||
|
||||
# Build tests, tutorials and python bindings
|
||||
option(LIBIGL_BUILD_TESTS "Build libigl unit test" ${LIBIGL_TOPLEVEL_PROJECT})
|
||||
option(LIBIGL_BUILD_TUTORIALS "Build libigl tutorial" ${LIBIGL_TOPLEVEL_PROJECT})
|
||||
option(LIBIGL_BUILD_PYTHON "Build libigl python bindings" ${LIBIGL_TOPLEVEL_PROJECT})
|
||||
|
||||
# USE_STATIC_LIBRARY speeds up the generation of multiple binaries,
|
||||
# at the cost of a longer initial compilation time
|
||||
# (by default, static build is off since libigl is a header-only library)
|
||||
option(LIBIGL_USE_STATIC_LIBRARY "Use LibIGL as static library" ON)
|
||||
|
||||
# All dependencies that are downloaded as cmake projects and tested on the auto-builds are ON
|
||||
# (by default, all build options are off)
|
||||
option(LIBIGL_WITH_COMISO "Use CoMiso" ON)
|
||||
option(LIBIGL_WITH_EMBREE "Use Embree" ON)
|
||||
option(LIBIGL_WITH_OPENGL "Use OpenGL" ON)
|
||||
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON)
|
||||
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" ON)
|
||||
option(LIBIGL_WITH_PNG "Use PNG" ON)
|
||||
option(LIBIGL_WITH_TETGEN "Use Tetgen" ON)
|
||||
option(LIBIGL_WITH_TRIANGLE "Use Triangle" ON)
|
||||
option(LIBIGL_WITH_XML "Use XML" ON)
|
||||
option(LIBIGL_WITH_PYTHON "Use Python" ${LIBIGL_BUILD_PYTHON})
|
||||
### End
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
### conditionally compile certain modules depending on libraries found on the system
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
|
||||
|
||||
### Adding libIGL: choose the path to your local copy libIGL
|
||||
include(libigl)
|
||||
|
||||
if(LIBIGL_BUILD_TUTORIALS)
|
||||
add_subdirectory(tutorial)
|
||||
endif()
|
||||
|
||||
if(LIBIGL_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(LIBIGL_WITH_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
@@ -1,268 +1,6 @@
|
||||
# libigl - A simple C++ geometry processing library
|
||||
[](https://travis-ci.org/libigl/libigl)
|
||||
[](https://ci.appveyor.com/project/danielepanozzo/libigl-6hjk1/branch/master)
|
||||

|
||||

|
||||
|
||||
<https://github.com/libigl/libigl/>
|
||||
|
||||
> Get started with:
|
||||
>
|
||||
```bash
|
||||
git clone --recursive https://github.com/libigl/libigl.git
|
||||
```
|
||||
|
||||
libigl is a simple C++ geometry processing library. We have a wide
|
||||
functionality including construction of sparse discrete differential geometry
|
||||
operators and finite-elements matrices such as the cotangent Laplacian and
|
||||
diagonalized mass matrix, simple facet and edge-based topology data structures,
|
||||
mesh-viewing utilities for OpenGL and GLSL, and many core functions for matrix
|
||||
manipulation which make [Eigen](http://eigen.tuxfamily.org) feel a lot more
|
||||
like MATLAB.
|
||||
|
||||
It is **a header-only library**. You do not need to compile anything to use,
|
||||
just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run. Each
|
||||
header file contains a single function (e.g. `igl/cotmatrix.h` contains
|
||||
`igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
|
||||
stored in an n-by-3 matrix of vertex positions `V` and an m-by-3 matrix of
|
||||
triangle indices `F`.
|
||||
|
||||
_Optionally_ the library may also be [pre-compiled](http://libigl.github.io/libigl/static-library/) into a statically
|
||||
linked library, for faster compile times with your projects. This only effects
|
||||
compile time (run-time performance and behavior is identical). If in doubt, use
|
||||
the header-only default mode: (i.e. just include the headers you want to use).
|
||||
|
||||
We use the [Eigen](http://eigen.tuxfamily.org) library heavily in our code. Our
|
||||
group prototypes a lot in MATLAB, and we have a useful [MATLAB to libigl+Eigen
|
||||
conversion table](matlab-to-eigen.html).
|
||||
|
||||
We regularly test compiling our library on Mac OS X with clang, Linux with gcc
|
||||
and Windows with Visual Studio 2015 Community Edition.
|
||||
|
||||
## Tutorial
|
||||
|
||||
As of version 1.0, libigl includes an introductory
|
||||
[tutorial](http://libigl.github.io/libigl/tutorial) that covers many functionalities.
|
||||
|
||||
## libigl Example Project
|
||||
|
||||
We provide a [blank project example](https://github.com/libigl/libigl-example-project) showing how to use libigl and cmake. Feel free and encouraged to copy or fork this project as a way of starting a new personal project using libigl.
|
||||
|
||||
## Coding Guidelines and Tips
|
||||
|
||||
libigl follows strict coding guidelines, please take a look [here](http://libigl.github.io/libigl/style-guidelines) before submitting your pull requests. We also have a set of [general coding tips](http://libigl.github.io/libigl/coding-guidelines) on how to code a geometry processing research project.
|
||||
|
||||
## Installation
|
||||
|
||||
Libigl is a **header-only** library. You do **not** need to build anything to
|
||||
install. Simply add `libigl/include` to your include path and include relevant
|
||||
headers. Here is a small "Hello, World" program:
|
||||
|
||||
```cpp
|
||||
#include <igl/cotmatrix.h>
|
||||
#include <Eigen/Dense>
|
||||
#include <Eigen/Sparse>
|
||||
#include <iostream>
|
||||
int main()
|
||||
{
|
||||
Eigen::MatrixXd V(4,2);
|
||||
V<<0,0,
|
||||
1,0,
|
||||
1,1,
|
||||
0,1;
|
||||
Eigen::MatrixXi F(2,3);
|
||||
F<<0,1,2,
|
||||
0,2,3;
|
||||
Eigen::SparseMatrix<double> L;
|
||||
igl::cotmatrix(V,F,L);
|
||||
std::cout<<"Hello, mesh: "<<std::endl<<L*V<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
If you save this in `hello.cpp`, then you could compile this with (assuming
|
||||
Eigen is installed in `/usr/local/include/eigen3`):
|
||||
|
||||
```bash
|
||||
g++ -std=c++11 -I/usr/local/include/eigen3 -I./libigl/include/ hello.cpp -o hello
|
||||
```
|
||||
|
||||
Running `./hello` would then produce
|
||||
|
||||
```
|
||||
Hello, mesh:
|
||||
0.5 0.5
|
||||
-0.5 0.5
|
||||
-0.5 -0.5
|
||||
0.5 -0.5
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
Dependencies are on a per-include basis and the majority of the functions in
|
||||
libigl depends only on the [Eigen](http://eigen.tuxfamily.org) library.
|
||||
|
||||
For more information see our [tutorial](http://libigl.github.io/libigl/tutorial).
|
||||
|
||||
### Optional Dependencies
|
||||
|
||||
Libigl compartmentalizes its **optional** dependences via its directory
|
||||
organization in the `include/` folder. All header files located _directly_ in
|
||||
the `include/igl/` folder have only stl and Eigen as dependencies. For example,
|
||||
all of the headers that depend on CGAL are located in `include/igl/copyleft/cgal`.
|
||||
For a full list of _optional_ dependencies check `optional/CMakeLists.txt`.
|
||||
|
||||
### GCC and the Optional CGAL Dependency
|
||||
The `include/igl/copyleft/cgal/*.h` headers depend on CGAL. It has come to
|
||||
our attention that CGAL does not work properly with GCC 4.8. To the best of
|
||||
our knowledge, GCC 4.7 and clang will work correctly.
|
||||
|
||||
### OpenMP and Windows
|
||||
Some of our functions will take advantage of OpenMP if available. However, it
|
||||
has come to our attention that Visual Studio + Eigen + OpenMP does not work
|
||||
properly. Since we use OpenMP only to improve performance, we recommend
|
||||
avoiding OpenMP on Windows or proceeding with caution.
|
||||
|
||||
## Download
|
||||
You can keep up to date by cloning a read-only copy of our GitHub
|
||||
[repository](https://github.com/libigl).
|
||||
|
||||
## Known Issues
|
||||
We rely heavily on Eigen. Nearly all inputs and outputs are Eigen matrices of
|
||||
some kind. However, we currently _only_ officially support Eigen's default
|
||||
column-major ordering. That means, we **do not** expect our code to work for
|
||||
matrices using the `Eigen::RowMajor` flag. If you can, change definitions like:
|
||||
|
||||
```cpp
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::RowMajor> A;
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```cpp
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::ColMajor> A;
|
||||
// or simply
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> A;
|
||||
```
|
||||
|
||||
We hope to fix this, or at least identify which functions are safe (many of
|
||||
them probably work just fine). This requires setting up unit testing, which is
|
||||
a major _todo_ for our development.
|
||||
|
||||
## Git Submodules
|
||||
Libigl uses git submodules for its _optional_ dependencies,
|
||||
in particular, those needed by the OpenGL viewer to run the examples in the
|
||||
[tutorial](http://libigl.github.io/libigl/tutorial). Git submodules allow use to treat clones of
|
||||
other libraries as sub-directories within ours while separating our commits.
|
||||
Read the [documentation](http://git-scm.com/docs/git-submodule) for a detailed
|
||||
explanation, but essentially our libigl repo stores a hash for each of its
|
||||
subrepos containing which version to update to. When a change is introduced in
|
||||
a dependencies repo we can incorporate that change by pulling in our sub-repo
|
||||
and updating (i.e. committing) that change to the hash.
|
||||
|
||||
When pulling new changes to libigl it's also a good idea to update changes to
|
||||
subrepos:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
git submodule update --recursive
|
||||
```
|
||||
|
||||
## Unit Testing
|
||||
|
||||
Libigl maintains [separate
|
||||
repository](https://github.com/libigl/libigl-unit-tests) for unit testing.
|
||||
|
||||
## How to Contribute
|
||||
|
||||
If you are interested in joining development, please fork the repository and
|
||||
submit a [pull request](https://help.github.com/articles/using-pull-requests/)
|
||||
with your changes. libigl follows strict coding guidelines, please take a look at our [style guidelines](http://libigl.github.io/libigl/style-guidelines) before submitting your pull requests.
|
||||
|
||||
## License
|
||||
libigl is primarily [MPL2](http://www.mozilla.org/MPL/2.0/) licensed
|
||||
([FAQ](http://www.mozilla.org/MPL/2.0/FAQ.html)). Some files contain
|
||||
third-party code under other licenses. We're currently in the processes of
|
||||
identifying these and marking appropriately.
|
||||
|
||||
## Attribution
|
||||
If you use libigl in your academic projects, please cite the papers we
|
||||
implement as appropriate. To cite the library in general, you could use this
|
||||
BibTeX entry:
|
||||
|
||||
```bibtex
|
||||
@misc{libigl,
|
||||
title = {{libigl}: A simple {C++} geometry processing library},
|
||||
author = {Alec Jacobson and Daniele Panozzo and others},
|
||||
note = {http://libigl.github.io/libigl/},
|
||||
year = {2017},
|
||||
}
|
||||
```
|
||||
|
||||
## Projects/Universities using libigl
|
||||
Libigl is used by many research groups around the world. In 2015, it won the
|
||||
Eurographics/ACM Symposium on Geometry Processing software award. Here are a
|
||||
few labs/companies/institutions using libigl:
|
||||
|
||||
- [Activision](http://www.activision.com)
|
||||
- [Adobe Research](http://www.adobe.com/technology/)
|
||||
- [Electronic Arts, Inc](http://www.ea.com)
|
||||
- [Epic Games](https://epicgames.com)
|
||||
- [Google Research](https://research.google.com)
|
||||
- [Industrial Light and Magic](http://ilm.com)
|
||||
- [Mesh consultants](http://meshconsultants.ca/), Canada
|
||||
- [Microsoft Research](https://www.microsoft.com/en-us/research/)
|
||||
- [Pixar](http://graphics.pixar.com/research/)
|
||||
- [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
|
||||
- [vvvv toolkit](http://vvvv.org) a multipurpose tookit
|
||||
- Columbia University, [Columbia Computer Graphics Group](http://www.cs.columbia.edu/cg/), USA
|
||||
- [Cornell University](http://www.graphics.cornell.edu/), USA
|
||||
- [Czech Technical University in Prague](http://dcgi.felk.cvut.cz/), Czech
|
||||
- EPF Lausanne, [Computer Graphics and Geometry Laboratory](http://lgg.epfl.ch/people.php), Switzerland
|
||||
- ETH Zurich, [Interactive Geometry Lab](http://igl.ethz.ch/) and [Advanced Technologies Lab](http://ait.inf.ethz.ch/), Swizterland
|
||||
- George Mason University, [CraGL](http://cs.gmu.edu/~ygingold/), USA
|
||||
- [Hong Kong University of Science and Technology](http://www.ust.hk/), Hong Kong
|
||||
- [Inria, Université Grenoble Alpes](https://www.inria.fr/centre/grenoble/), France
|
||||
- [Jiangnan university](http://english.jiangnan.edu.cn), China
|
||||
- [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan
|
||||
- New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
|
||||
- NYUPoly, [Game Innovation Lab](http://game.engineering.nyu.edu/), USA
|
||||
- [TU Berlin](https://www.cg.tu-berlin.de), Germany
|
||||
- [TU Delft](http://www.tudelft.nl/en/), Netherlands
|
||||
- [TU Wien](https://www.tuwien.ac.at/en/tuwien_home/), Austria
|
||||
- [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France
|
||||
- [UBISOFT](https://www.ubisoft.com/en-us/), USA
|
||||
- [Utrecht University](http://www.staff.science.uu.nl/~vaxma001/), The Netherlands
|
||||
- [Universidade Federal de Santa Catarina](http://mtm.ufsc.br/~leo/), Brazil
|
||||
- [University College London](http://vecg.cs.ucl.ac.uk/), England
|
||||
- [University of California Berkeley](http://vis.berkeley.edu/), USA
|
||||
- [University of Cambridge](http://www.cam.ac.uk/), England
|
||||
- [University of Pennsylvania](http://cg.cis.upenn.edu/), USA
|
||||
- [University of Texas at Austin](http://www.cs.utexas.edu/users/evouga/), USA
|
||||
- [University of Toronto](http://dgp.toronto.edu), Canada
|
||||
- [University of Victoria](https://www.csc.uvic.ca/Research/graphics/), Canada
|
||||
- [University of Wisconsin-Eau Claire](http://www.uwec.edu/computer-science/), USA
|
||||
- [Università della Svizzera Italiana](http://www.usi.ch/en), Switzerland
|
||||
- [Université Toulouse III Paul Sabatier](http://www.univ-tlse3.fr/), France
|
||||
- [Zhejiang University](http://www.math.zju.edu.cn/cagd/), China
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
Libigl is a group endeavor led by [Alec
|
||||
Jacobson](http://www.cs.toronto.edu/~jacobson/) and [Daniele
|
||||
Panozzo](http://cs.nyu.edu/~panozzo/). Please [contact
|
||||
us](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com) if you have
|
||||
questions or comments. For troubleshooting, please post an
|
||||
[issue](https://github.com/libigl/libigl/issues) on github.
|
||||
|
||||
If you're using libigl in your projects, quickly [drop us a
|
||||
note](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com). Tell us who you
|
||||
are and what you're using it for. This helps us apply for funding and justify
|
||||
spending time maintaining this.
|
||||
|
||||
If you find bugs or have problems please use our [github issue tracking
|
||||
page](https://github.com/libigl/libigl/issues).
|
||||
|
||||
## Copyright
|
||||
2017 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan Zhou, Sebastian Koch, Jeremie Dumas, Amir Vaxman, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.
|
||||
|
||||
Please see individual files for appropriate copyright notices.
|
||||
Documentation, tutorial, and instructions at <https://libigl.github.io>.
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# This file should contain the current version number of libigl
|
||||
# World.Major.Minor
|
||||
# Anyone may increment Minor to indicate a small change.
|
||||
# Major indicates a large change or large number of changes (upload to website)
|
||||
# World indicates a substantial change or release
|
||||
1.2.1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
################################################################################
|
||||
include(DownloadProject)
|
||||
|
||||
# With CMake 3.8 and above, we can hide warnings about git being in a
|
||||
# detached head by passing an extra GIT_CONFIG option
|
||||
if(NOT (${CMAKE_VERSION} VERSION_LESS "3.8.0"))
|
||||
set(LIBIGL_EXTRA_OPTIONS "GIT_CONFIG advice.detachedHead=false")
|
||||
else()
|
||||
set(LIBIGL_EXTRA_OPTIONS "")
|
||||
endif()
|
||||
|
||||
# Shortcut function
|
||||
function(igl_download_project name)
|
||||
download_project(
|
||||
PROJ ${name}
|
||||
SOURCE_DIR ${LIBIGL_EXTERNAL}/${name}
|
||||
DOWNLOAD_DIR ${LIBIGL_EXTERNAL}/.cache/${name}
|
||||
QUIET
|
||||
${LIBIGL_EXTRA_OPTIONS}
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
|
||||
## CGAL
|
||||
function(igl_download_cgal)
|
||||
igl_download_project(cgal
|
||||
GIT_REPOSITORY https://github.com/CGAL/cgal.git
|
||||
GIT_TAG f7c3c8212b56c0d6dae63787efc99093f4383415
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## CoMISo
|
||||
function(igl_download_comiso)
|
||||
igl_download_project(CoMISo
|
||||
GIT_REPOSITORY https://github.com/libigl/CoMISo.git
|
||||
GIT_TAG fea3ee0ba7d42ee3eca202d484e4fad855e4d6aa
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Cork
|
||||
function(igl_download_cork)
|
||||
igl_download_project(cork
|
||||
GIT_REPOSITORY https://github.com/libigl/cork.git
|
||||
GIT_TAG 27ad8a285838f5a480d856429e39d3d56d4338f9
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Eigen
|
||||
function(igl_download_eigen)
|
||||
igl_download_project(eigen
|
||||
URL http://bitbucket.org/eigen/eigen/get/3.2.10.tar.gz
|
||||
URL_MD5 8ad10ac703a78143a4062c9bda9d8fd3
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Embree
|
||||
function(igl_download_embree)
|
||||
igl_download_project(embree
|
||||
URL https://github.com/embree/embree/archive/v2.17.4.tar.gz
|
||||
URL_MD5 2038f3216b1d626e87453aee72c470e5
|
||||
# GIT_REPOSITORY https://github.com/embree/embree.git
|
||||
# GIT_TAG cb61322db3bb7082caed21913ad14869b436fe78
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## glad
|
||||
function(igl_download_glad)
|
||||
igl_download_project(glad
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-glad.git
|
||||
GIT_TAG 71e35fe685a0cc160068a2f2f971c40b82d14af0
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## GLFW
|
||||
function(igl_download_glfw)
|
||||
igl_download_project(glfw
|
||||
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||
GIT_TAG 58cc4b2c5c2c9a245e09451437dd6f5af4d60c84
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## ImGui
|
||||
function(igl_download_imgui)
|
||||
igl_download_project(imgui
|
||||
GIT_REPOSITORY https://github.com/ocornut/imgui.git
|
||||
GIT_TAG bc6ac8b2aee0614debd940e45bc9cd0d9b355c86
|
||||
)
|
||||
igl_download_project(libigl-imgui
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-imgui.git
|
||||
GIT_TAG a37e6e59e72fb07bd787dc7e90f72b9e1928dae7
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## pybind11
|
||||
function(igl_download_pybind11)
|
||||
igl_download_project(pybind11
|
||||
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
||||
GIT_TAG 2d0507db43cd5a117f7843e053b17dffca114107
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## stb_image
|
||||
function(igl_download_stb)
|
||||
igl_download_project(stb
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-stb.git
|
||||
GIT_TAG e671ceb3def5e7029a23de14c55dc16301ad4dab
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## TetGen
|
||||
function(igl_download_tetgen)
|
||||
igl_download_project(tetgen
|
||||
GIT_REPOSITORY https://github.com/libigl/tetgen.git
|
||||
GIT_TAG d2dcc33cb8551f16e302c8130ce12fa52992cd09
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## TinyXML
|
||||
function(igl_download_tinyxml2)
|
||||
igl_download_project(tinyxml2
|
||||
GIT_REPOSITORY https://github.com/leethomason/tinyxml2.git
|
||||
GIT_TAG d175e9de0be0d4db75d0a8cf065599a435a87eb6
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Triangle
|
||||
function(igl_download_triangle)
|
||||
igl_download_project(triangle
|
||||
GIT_REPOSITORY https://github.com/libigl/triangle.git
|
||||
GIT_TAG d6761dd691e2e1318c83bf7773fea88d9437464a
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Google test
|
||||
function(igl_download_googletest)
|
||||
igl_download_project(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest
|
||||
GIT_TAG release-1.8.1
|
||||
)
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
|
||||
## Test data
|
||||
function(igl_download_test_data)
|
||||
set(IGL_TEST_DATA ${LIBIGL_EXTERNAL}/../tests/data)
|
||||
|
||||
download_project(
|
||||
PROJ test_data
|
||||
SOURCE_DIR ${IGL_TEST_DATA}
|
||||
DOWNLOAD_DIR ${LIBIGL_EXTERNAL}/.cache/test_data
|
||||
QUIET
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-tests-data
|
||||
GIT_TAG c81bb3b3db4cfd78bac6d359d845c45bc1059c9a
|
||||
${LIBIGL_EXTRA_OPTIONS}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
## Tutorial data
|
||||
function(igl_download_tutorial_data)
|
||||
set(IGL_TUTORIAL_DATA ${LIBIGL_EXTERNAL}/../tutorial/data)
|
||||
|
||||
download_project(
|
||||
PROJ tutorial_data
|
||||
SOURCE_DIR ${IGL_TUTORIAL_DATA}
|
||||
DOWNLOAD_DIR ${LIBIGL_EXTERNAL}/.cache/tutorial_data
|
||||
QUIET
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-tutorial-data
|
||||
GIT_TAG 5c6a1ea809c043d71e5595775709c15325a7158c
|
||||
${LIBIGL_EXTRA_OPTIONS}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/libigl-export.cmake)
|
||||
|
||||
if (TARGET igl::core)
|
||||
if (NOT TARGET Eigen3::Eigen)
|
||||
find_package(Eigen3 QUIET)
|
||||
if (NOT Eigen3_FOUND)
|
||||
# try with PkgCOnfig
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(Eigen3 QUIET IMPORTED_TARGET eigen3)
|
||||
endif()
|
||||
|
||||
if (NOT Eigen3_FOUND)
|
||||
message(FATAL_ERROR "Could not find required dependency Eigen3")
|
||||
set(libigl_core_FOUND FALSE)
|
||||
else()
|
||||
target_link_libraries(igl::core INTERFACE PkgConfig::Eigen3)
|
||||
set(libigl_core_FOUND TRUE)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(igl::core INTERFACE Eigen3::Eigen)
|
||||
set(libigl_core_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
check_required_components(libigl)
|
||||
|
||||
@@ -11,48 +11,35 @@ if(APPLE)
|
||||
message(STATUS "Found libtool - ${CMAKE_LIBTOOL}")
|
||||
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
foreach(lang ${languages})
|
||||
# Added -c
|
||||
# Added -c
|
||||
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
|
||||
"${CMAKE_LIBTOOL} -c -static -o <TARGET> <LINK_FLAGS> <OBJECTS> ")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
### Find packages to populate default options ###
|
||||
#
|
||||
# COMPONENTS should match subsequent calls
|
||||
find_package(Matlab COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY) # --> Matlab_FOUND
|
||||
find_package(MOSEK) # --> MOSEK_FOUND
|
||||
find_package(OpenGL) # --> OPENGL_FOUND
|
||||
|
||||
### Available options ###
|
||||
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" ON)
|
||||
option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF)
|
||||
option(LIBIGL_WITH_CGAL "Use CGAL" ON)
|
||||
option(LIBIGL_WITH_COMISO "Use CoMiso" ON)
|
||||
option(LIBIGL_WITH_CORK "Use Cork" OFF)
|
||||
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
|
||||
option(LIBIGL_WITH_LIM "Use LIM" ON)
|
||||
option(LIBIGL_WITH_MATLAB "Use Matlab" "${Matlab_FOUND}")
|
||||
option(LIBIGL_WITH_MOSEK "Use MOSEK" "${MOSEK_FOUND}")
|
||||
option(LIBIGL_WITH_OPENGL "Use OpenGL" "${OPENGL_FOUND}")
|
||||
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" "${OPENGL_FOUND}")
|
||||
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" OFF)
|
||||
option(LIBIGL_WITH_PNG "Use PNG" ON)
|
||||
option(LIBIGL_WITH_TETGEN "Use Tetgen" ON)
|
||||
option(LIBIGL_WITH_TRIANGLE "Use Triangle" ON)
|
||||
option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" "${OPENGL_FOUND}")
|
||||
option(LIBIGL_WITH_XML "Use XML" ON)
|
||||
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
|
||||
|
||||
if(LIBIGL_WITH_VIEWER AND (NOT LIBIGL_WITH_OPENGL_GLFW OR NOT LIBIGL_WITH_OPENGL) )
|
||||
message(FATAL_ERROR "LIBIGL_WITH_VIEWER=ON requires LIBIGL_WITH_OPENGL_GLFW=ON and LIBIGL_WITH_OPENGL=ON")
|
||||
endif()
|
||||
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF)
|
||||
option(LIBIGL_WITH_CGAL "Use CGAL" OFF)
|
||||
option(LIBIGL_WITH_COMISO "Use CoMiso" OFF)
|
||||
option(LIBIGL_WITH_CORK "Use Cork" OFF)
|
||||
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
|
||||
option(LIBIGL_WITH_MATLAB "Use Matlab" OFF)
|
||||
option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF)
|
||||
option(LIBIGL_WITH_OPENGL "Use OpenGL" OFF)
|
||||
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" OFF)
|
||||
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" OFF)
|
||||
option(LIBIGL_WITH_PNG "Use PNG" OFF)
|
||||
option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF)
|
||||
option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF)
|
||||
option(LIBIGL_WITH_XML "Use XML" OFF)
|
||||
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
|
||||
option(LIBIGL_WITHOUT_COPYLEFT "Disable Copyleft libraries" OFF)
|
||||
|
||||
################################################################################
|
||||
|
||||
### Configuration
|
||||
set(LIBIGL_ROOT "${CMAKE_CURRENT_LIST_DIR}/../..")
|
||||
set(LIBIGL_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")
|
||||
set(LIBIGL_SOURCE_DIR "${LIBIGL_ROOT}/include")
|
||||
set(LIBIGL_EXTERNAL "${LIBIGL_ROOT}/external")
|
||||
|
||||
@@ -63,12 +50,21 @@ else()
|
||||
set(IGL_SCOPE INTERFACE)
|
||||
endif()
|
||||
|
||||
# Download and update 3rdparty libraries
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include(LibiglDownloadExternal)
|
||||
|
||||
################################################################################
|
||||
### IGL Common
|
||||
################################################################################
|
||||
|
||||
add_library(igl_common INTERFACE)
|
||||
target_include_directories(igl_common SYSTEM INTERFACE ${LIBIGL_SOURCE_DIR})
|
||||
target_include_directories(igl_common SYSTEM INTERFACE
|
||||
$<BUILD_INTERFACE:${LIBIGL_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
# Export igl_common as igl::common
|
||||
set_property(TARGET igl_common PROPERTY EXPORT_NAME igl::common)
|
||||
if(LIBIGL_USE_STATIC_LIBRARY)
|
||||
target_compile_definitions(igl_common INTERFACE -DIGL_STATIC_LIBRARY)
|
||||
endif()
|
||||
@@ -81,6 +77,9 @@ target_compile_features(igl_common INTERFACE ${CXX11_FEATURES})
|
||||
if(MSVC)
|
||||
# Enable parallel compilation for Visual Studio
|
||||
target_compile_options(igl_common INTERFACE /MP /bigobj)
|
||||
if(LIBIGL_WITH_CGAL)
|
||||
target_compile_options(igl_common INTERFACE "/MD$<$<CONFIG:Debug>:d>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
@@ -88,12 +87,21 @@ if(BUILD_SHARED_LIBS)
|
||||
set_target_properties(igl_common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
endif()
|
||||
|
||||
# Eigen
|
||||
if(TARGET Eigen3::Eigen)
|
||||
# If an imported target already exists, use it
|
||||
target_link_libraries(igl_common INTERFACE Eigen3::Eigen)
|
||||
else()
|
||||
target_include_directories(igl_common SYSTEM INTERFACE ${LIBIGL_EXTERNAL}/eigen)
|
||||
igl_download_eigen()
|
||||
target_include_directories(igl_common SYSTEM INTERFACE
|
||||
$<BUILD_INTERFACE:${LIBIGL_EXTERNAL}/eigen>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
endif()
|
||||
|
||||
# C++11 Thread library
|
||||
@@ -102,20 +110,6 @@ target_link_libraries(igl_common INTERFACE ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
################################################################################
|
||||
|
||||
include(DownloadProject)
|
||||
|
||||
# Shortcut function
|
||||
function(igl_download_project name)
|
||||
download_project(
|
||||
PROJ ${name}
|
||||
SOURCE_DIR ${LIBIGL_EXTERNAL}/${name}
|
||||
DOWNLOAD_DIR ${LIBIGL_EXTERNAL}/.cache/${name}
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
|
||||
## CGAL dependencies on Windows: GMP & MPFR
|
||||
function(igl_download_cgal_deps)
|
||||
if(WIN32)
|
||||
@@ -143,8 +137,12 @@ function(compile_igl_module module_dir)
|
||||
endif()
|
||||
if(LIBIGL_USE_STATIC_LIBRARY)
|
||||
file(GLOB SOURCES_IGL_${module_name}
|
||||
"${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.cpp"
|
||||
"${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.cpp")
|
||||
"${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.cpp")
|
||||
if(NOT LIBIGL_WITHOUT_COPYLEFT)
|
||||
file(GLOB COPYLEFT_SOURCES_IGL_${module_name}
|
||||
"${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.cpp")
|
||||
list(APPEND SOURCES_IGL_${module_name} ${COPYLEFT_SOURCES_IGL_${module_name}})
|
||||
endif()
|
||||
add_library(${module_libname} STATIC ${SOURCES_IGL_${module_name}} ${ARGN})
|
||||
if(MSVC)
|
||||
target_compile_options(${module_libname} PRIVATE /w) # disable all warnings (not ideal but...)
|
||||
@@ -163,6 +161,8 @@ function(compile_igl_module module_dir)
|
||||
# Alias target because it looks nicer
|
||||
message(STATUS "Creating target: igl::${module_name} (${module_libname})")
|
||||
add_library(igl::${module_name} ALIAS ${module_libname})
|
||||
# Export as igl::${module_name}
|
||||
set_property(TARGET ${module_libname} PROPERTY EXPORT_NAME igl::${module_name})
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
@@ -177,15 +177,9 @@ endif()
|
||||
compile_igl_module("core" ${SOURCES_IGL})
|
||||
|
||||
################################################################################
|
||||
## Compile the AntTweakBar part ###
|
||||
if(LIBIGL_WITH_ANTTWEAKBAR)
|
||||
set(ANTTWEAKBAR_DIR "${LIBIGL_EXTERNAL}/AntTweakBar")
|
||||
if(NOT TARGET AntTweakBar)
|
||||
add_subdirectory("${ANTTWEAKBAR_DIR}" AntTweakBar)
|
||||
endif()
|
||||
compile_igl_module("anttweakbar")
|
||||
target_link_libraries(igl_anttweakbar ${IGL_SCOPE} AntTweakBar)
|
||||
target_include_directories(igl_anttweakbar ${IGL_SCOPE} "${ANTTWEAKBAR_DIR}/include")
|
||||
### Download the python part ###
|
||||
if(LIBIGL_WITH_PYTHON)
|
||||
igl_download_pybind11()
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
@@ -196,11 +190,12 @@ if(LIBIGL_WITH_CGAL)
|
||||
# `Exact_predicates_exact_constructions_kernel_with_sqrt`
|
||||
if(NOT TARGET CGAL::CGAL)
|
||||
set(CGAL_DIR "${LIBIGL_EXTERNAL}/cgal")
|
||||
igl_download_cgal()
|
||||
igl_download_cgal_deps()
|
||||
if(EXISTS ${LIBIGL_EXTERNAL}/boost)
|
||||
set(BOOST_ROOT "${LIBIGL_EXTERNAL}/boost")
|
||||
endif()
|
||||
set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
|
||||
option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" ON)
|
||||
find_package(CGAL CONFIG COMPONENTS Core PATHS ${CGAL_DIR} NO_DEFAULT_PATH)
|
||||
endif()
|
||||
|
||||
@@ -242,6 +237,7 @@ endfunction()
|
||||
if(LIBIGL_WITH_COMISO)
|
||||
compile_igl_module("comiso")
|
||||
if(NOT TARGET CoMISo)
|
||||
igl_download_comiso()
|
||||
add_subdirectory("${LIBIGL_EXTERNAL}/CoMISo" CoMISo)
|
||||
endif()
|
||||
target_link_libraries(igl_comiso ${IGL_SCOPE} CoMISo)
|
||||
@@ -254,6 +250,7 @@ if(LIBIGL_WITH_CORK)
|
||||
if(NOT TARGET cork)
|
||||
# call this "lib-cork" instead of "cork", otherwise cmake gets confused about
|
||||
# "cork" executable
|
||||
igl_download_cork()
|
||||
add_subdirectory("${CORK_DIR}" "lib-cork")
|
||||
endif()
|
||||
compile_igl_module("cork")
|
||||
@@ -282,6 +279,7 @@ if(LIBIGL_WITH_EMBREE)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET embree)
|
||||
igl_download_embree()
|
||||
add_subdirectory("${EMBREE_DIR}" "embree")
|
||||
endif()
|
||||
|
||||
@@ -301,18 +299,6 @@ if(LIBIGL_WITH_EMBREE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
### Compile the lim part ###
|
||||
if(LIBIGL_WITH_LIM)
|
||||
set(LIM_DIR "${LIBIGL_EXTERNAL}/lim")
|
||||
if(NOT TARGET lim)
|
||||
add_subdirectory("${LIM_DIR}" "lim")
|
||||
endif()
|
||||
compile_igl_module("lim")
|
||||
target_link_libraries(igl_lim ${IGL_SCOPE} lim)
|
||||
target_include_directories(igl_lim ${IGL_SCOPE} ${LIM_DIR})
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
### Compile the matlab part ###
|
||||
if(LIBIGL_WITH_MATLAB)
|
||||
@@ -343,6 +329,7 @@ if(LIBIGL_WITH_OPENGL)
|
||||
|
||||
# glad module
|
||||
if(NOT TARGET glad)
|
||||
igl_download_glad()
|
||||
add_subdirectory(${LIBIGL_EXTERNAL}/glad glad)
|
||||
endif()
|
||||
target_link_libraries(igl_opengl ${IGL_SCOPE} glad)
|
||||
@@ -359,6 +346,7 @@ if(LIBIGL_WITH_OPENGL_GLFW)
|
||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE)
|
||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL " " FORCE)
|
||||
set(GLFW_INSTALL OFF CACHE BOOL " " FORCE)
|
||||
igl_download_glfw()
|
||||
add_subdirectory(${LIBIGL_EXTERNAL}/glfw glfw)
|
||||
endif()
|
||||
target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw)
|
||||
@@ -372,7 +360,8 @@ if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
|
||||
# ImGui module
|
||||
compile_igl_module("opengl/glfw/imgui")
|
||||
if(NOT TARGET imgui)
|
||||
add_subdirectory(${LIBIGL_EXTERNAL}/imgui imgui)
|
||||
igl_download_imgui()
|
||||
add_subdirectory(${LIBIGL_EXTERNAL}/libigl-imgui imgui)
|
||||
endif()
|
||||
target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui)
|
||||
endif()
|
||||
@@ -384,9 +373,9 @@ if(LIBIGL_WITH_PNG)
|
||||
# png/ module is anomalous because it also depends on opengl it really should
|
||||
# be moved into the opengl/ directory and namespace ...
|
||||
if(TARGET igl_opengl)
|
||||
set(STB_IMAGE_DIR "${LIBIGL_EXTERNAL}/stb_image")
|
||||
if(NOT TARGET stb_image)
|
||||
add_subdirectory("${STB_IMAGE_DIR}" "stb_image")
|
||||
igl_download_stb()
|
||||
add_subdirectory(${LIBIGL_EXTERNAL}/stb stb_image)
|
||||
endif()
|
||||
compile_igl_module("png" "")
|
||||
target_link_libraries(igl_png ${IGL_SCOPE} igl_stb_image igl_opengl)
|
||||
@@ -398,6 +387,7 @@ endif()
|
||||
if(LIBIGL_WITH_TETGEN)
|
||||
set(TETGEN_DIR "${LIBIGL_EXTERNAL}/tetgen")
|
||||
if(NOT TARGET tetgen)
|
||||
igl_download_tetgen()
|
||||
add_subdirectory("${TETGEN_DIR}" "tetgen")
|
||||
endif()
|
||||
compile_igl_module("tetgen")
|
||||
@@ -410,6 +400,7 @@ endif()
|
||||
if(LIBIGL_WITH_TRIANGLE)
|
||||
set(TRIANGLE_DIR "${LIBIGL_EXTERNAL}/triangle")
|
||||
if(NOT TARGET triangle)
|
||||
igl_download_triangle()
|
||||
add_subdirectory("${TRIANGLE_DIR}" "triangle")
|
||||
endif()
|
||||
compile_igl_module("triangle")
|
||||
@@ -422,7 +413,9 @@ endif()
|
||||
if(LIBIGL_WITH_XML)
|
||||
set(TINYXML2_DIR "${LIBIGL_EXTERNAL}/tinyxml2")
|
||||
if(NOT TARGET tinyxml2)
|
||||
igl_download_tinyxml2()
|
||||
add_library(tinyxml2 STATIC ${TINYXML2_DIR}/tinyxml2.cpp ${TINYXML2_DIR}/tinyxml2.h)
|
||||
target_include_directories(tinyxml2 PUBLIC ${TINYXML2_DIR})
|
||||
set_target_properties(tinyxml2 PROPERTIES
|
||||
COMPILE_DEFINITIONS "TINYXML2_EXPORT"
|
||||
VERSION "3.0.0"
|
||||
@@ -432,3 +425,82 @@ if(LIBIGL_WITH_XML)
|
||||
target_link_libraries(igl_xml ${IGL_SCOPE} tinyxml2)
|
||||
target_include_directories(igl_xml ${IGL_SCOPE} ${TINYXML2_DIR})
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
### Install and export all modules
|
||||
|
||||
function(install_dir_files dir_name)
|
||||
if (dir_name STREQUAL "core")
|
||||
set(subpath "")
|
||||
else()
|
||||
set(subpath "/${dir_name}")
|
||||
endif()
|
||||
|
||||
file(GLOB public_headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.h
|
||||
)
|
||||
|
||||
set(files_to_install ${public_headers})
|
||||
|
||||
if(NOT LIBIGL_USE_STATIC_LIBRARY)
|
||||
file(GLOB public_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.cpp
|
||||
)
|
||||
endif()
|
||||
list(APPEND files_to_install ${public_sources})
|
||||
|
||||
install(
|
||||
FILES ${files_to_install}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/igl${subpath}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# Install and export core library
|
||||
install(
|
||||
TARGETS
|
||||
igl
|
||||
igl_common
|
||||
EXPORT igl-export
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
export(
|
||||
TARGETS
|
||||
igl
|
||||
igl_common
|
||||
FILE libigl-export.cmake
|
||||
)
|
||||
|
||||
# Install headers for core library
|
||||
install_dir_files(core)
|
||||
install_dir_files(copyleft)
|
||||
|
||||
# Write package configuration file
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/libigl-config.cmake.in
|
||||
${CMAKE_BINARY_DIR}/libigl-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/libigl/cmake
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_BINARY_DIR}/libigl-config.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DATADIR}/libigl/cmake
|
||||
)
|
||||
|
||||
# Write export file
|
||||
export(EXPORT igl-export
|
||||
FILE "${CMAKE_BINARY_DIR}/libigl-export.cmake"
|
||||
)
|
||||
install(EXPORT igl-export DESTINATION ${CMAKE_INSTALL_DATADIR}/libigl/cmake FILE libigl-export.cmake)
|
||||
|
||||
|
||||
export(PACKAGE libigl)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Zhongshi Jiang <jiangzs@nyu.edu>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_MAPPINGENERGYTYPE_H
|
||||
#define IGL_MAPPINGENERGYTYPE_H
|
||||
namespace igl
|
||||
{
|
||||
// Energy Types used for Parameterization/Mapping.
|
||||
// Refer to SLIM [Rabinovich et al. 2017] for more details
|
||||
// Todo: Integrate with ARAPEnergyType
|
||||
|
||||
enum MappingEnergyType
|
||||
{
|
||||
ARAP,
|
||||
LOG_ARAP,
|
||||
SYMMETRIC_DIRICHLET,
|
||||
CONFORMAL,
|
||||
EXP_CONFORMAL,
|
||||
EXP_SYMMETRIC_DIRICHLET
|
||||
};
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
e8898a8aa8e920ab7c2cd0bfaac5acc2e4991daf
|
||||
@@ -165,4 +165,5 @@ template void igl::adjacency_list<Eigen::Matrix<int, -1, 2, 0, -1, 2>, int>(Eige
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::adjacency_list<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
|
||||
template void igl::adjacency_list<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
|
||||
template void igl::adjacency_list<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned int>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class std::vector<class std::vector<unsigned int, class std::allocator<unsigned int> >, class std::allocator<class std::vector<unsigned int, class std::allocator<unsigned int> > > > &, bool);
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "adjacency_matrix.h"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
template <typename DerivedF, typename T>
|
||||
IGL_INLINE void igl::adjacency_matrix(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::SparseMatrix<T>& A)
|
||||
{
|
||||
using namespace std;
|
||||
@@ -71,4 +71,5 @@ IGL_INLINE void igl::adjacency_matrix(
|
||||
template void igl::adjacency_matrix<Eigen::Matrix<int, -1, -1, 0, -1, -1>, bool>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<bool, 0, int>&);
|
||||
template void igl::adjacency_matrix<Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
|
||||
template void igl::adjacency_matrix<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<int, 0, int>&);
|
||||
template void igl::adjacency_matrix<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::SparseMatrix<int, 0, int>&);
|
||||
#endif
|
||||
|
||||
@@ -1,934 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "ReAntTweakBar.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
|
||||
// GLOBAL WRAPPERS
|
||||
namespace
|
||||
{
|
||||
std::map<
|
||||
TwType,std::pair<const char *,std::vector<TwEnumVal> >
|
||||
> ReTw_custom_types;
|
||||
}
|
||||
|
||||
IGL_INLINE TwType igl::anttweakbar::ReTwDefineEnum(
|
||||
const char *name,
|
||||
const TwEnumVal *enumValues,
|
||||
unsigned int nbValues)
|
||||
{
|
||||
using namespace std;
|
||||
// copy enum valus into vector
|
||||
std::vector<TwEnumVal> enum_vals;
|
||||
enum_vals.resize(nbValues);
|
||||
for(unsigned int j = 0; j<nbValues;j++)
|
||||
{
|
||||
enum_vals[j] = enumValues[j];
|
||||
}
|
||||
TwType type = TwDefineEnum(name,enumValues,nbValues);
|
||||
|
||||
ReTw_custom_types[type] =
|
||||
std::pair<const char *,std::vector<TwEnumVal> >(name,enum_vals);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
IGL_INLINE TwType igl::anttweakbar::ReTwDefineEnumFromString(
|
||||
const char * _Name,
|
||||
const char * _EnumString)
|
||||
{
|
||||
// Taken directly from TwMgr.cpp, just replace TwDefineEnum with
|
||||
// ReTwDefineEnum
|
||||
using namespace std;
|
||||
{
|
||||
if (_EnumString == NULL)
|
||||
return ReTwDefineEnum(_Name, NULL, 0);
|
||||
|
||||
// split enumString
|
||||
stringstream EnumStream(_EnumString);
|
||||
string Label;
|
||||
vector<string> Labels;
|
||||
while( getline(EnumStream, Label, ',') ) {
|
||||
// trim Label
|
||||
size_t Start = Label.find_first_not_of(" \n\r\t");
|
||||
size_t End = Label.find_last_not_of(" \n\r\t");
|
||||
if( Start==string::npos || End==string::npos )
|
||||
Label = "";
|
||||
else
|
||||
Label = Label.substr(Start, (End-Start)+1);
|
||||
// store Label
|
||||
Labels.push_back(Label);
|
||||
}
|
||||
// create TwEnumVal array
|
||||
vector<TwEnumVal> Vals(Labels.size());
|
||||
for( int i=0; i<(int)Labels.size(); i++ )
|
||||
{
|
||||
Vals[i].Value = i;
|
||||
// Wrong:
|
||||
//Vals[i].Label = Labels[i].c_str();
|
||||
// Allocate char on heap
|
||||
// http://stackoverflow.com/a/10050258/148668
|
||||
char * c_label = new char[Labels[i].length()+1];
|
||||
std::strcpy(c_label, Labels[i].c_str());
|
||||
Vals[i].Label = c_label;
|
||||
}
|
||||
|
||||
const TwType type =
|
||||
ReTwDefineEnum(_Name, Vals.empty() ?
|
||||
NULL :
|
||||
&(Vals[0]), (unsigned int)Vals.size());
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ReTwTypeString
|
||||
{
|
||||
TwType type;
|
||||
const char * type_str;
|
||||
};
|
||||
|
||||
#define RETW_NUM_DEFAULT_TYPE_STRINGS 23
|
||||
ReTwTypeString ReTwDefaultTypeStrings[RETW_NUM_DEFAULT_TYPE_STRINGS] =
|
||||
{
|
||||
{TW_TYPE_UNDEF,"TW_TYPE_UNDEF"},
|
||||
{TW_TYPE_BOOLCPP,"TW_TYPE_BOOLCPP"},
|
||||
{TW_TYPE_BOOL8,"TW_TYPE_BOOL8"},
|
||||
{TW_TYPE_BOOL16,"TW_TYPE_BOOL16"},
|
||||
{TW_TYPE_BOOL32,"TW_TYPE_BOOL32"},
|
||||
{TW_TYPE_CHAR,"TW_TYPE_CHAR"},
|
||||
{TW_TYPE_INT8,"TW_TYPE_INT8"},
|
||||
{TW_TYPE_UINT8,"TW_TYPE_UINT8"},
|
||||
{TW_TYPE_INT16,"TW_TYPE_INT16"},
|
||||
{TW_TYPE_UINT16,"TW_TYPE_UINT16"},
|
||||
{TW_TYPE_INT32,"TW_TYPE_INT32"},
|
||||
{TW_TYPE_UINT32,"TW_TYPE_UINT32"},
|
||||
{TW_TYPE_FLOAT,"TW_TYPE_FLOAT"},
|
||||
{TW_TYPE_DOUBLE,"TW_TYPE_DOUBLE"},
|
||||
{TW_TYPE_COLOR32,"TW_TYPE_COLOR32"},
|
||||
{TW_TYPE_COLOR3F,"TW_TYPE_COLOR3F"},
|
||||
{TW_TYPE_COLOR4F,"TW_TYPE_COLOR4F"},
|
||||
{TW_TYPE_CDSTRING,"TW_TYPE_CDSTRING"},
|
||||
{TW_TYPE_STDSTRING,"TW_TYPE_STDSTRING"},
|
||||
{TW_TYPE_QUAT4F,"TW_TYPE_QUAT4F"},
|
||||
{TW_TYPE_QUAT4D,"TW_TYPE_QUAT4D"},
|
||||
{TW_TYPE_DIR3F,"TW_TYPE_DIR3F"},
|
||||
{TW_TYPE_DIR3D,"TW_TYPE_DIR3D"}
|
||||
};
|
||||
}
|
||||
|
||||
IGL_INLINE igl::anttweakbar::ReTwBar::ReTwBar():
|
||||
bar(NULL),
|
||||
name(),
|
||||
rw_items(),cb_items()
|
||||
{
|
||||
}
|
||||
|
||||
IGL_INLINE igl::anttweakbar::ReTwBar::ReTwBar(
|
||||
const igl::anttweakbar::ReTwBar & that):
|
||||
bar(that.bar),
|
||||
name(that.name),
|
||||
rw_items(that.rw_items),
|
||||
cb_items(that.cb_items)
|
||||
{
|
||||
}
|
||||
|
||||
IGL_INLINE igl::anttweakbar::ReTwBar &
|
||||
igl::anttweakbar::ReTwBar::operator=(const igl::anttweakbar::ReTwBar & that)
|
||||
{
|
||||
// check for self assignment
|
||||
if(this != &that)
|
||||
{
|
||||
bar = that.bar;
|
||||
rw_items = that.rw_items;
|
||||
cb_items = that.cb_items;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// BAR WRAPPERS
|
||||
IGL_INLINE void igl::anttweakbar::ReTwBar::TwNewBar(const char * _name)
|
||||
{
|
||||
this->bar = ::TwNewBar(_name);
|
||||
// Alec: This causes trouble (not sure why) in multiple applications
|
||||
// (medit, puppet) Probably there is some sort of memory corrpution.
|
||||
// this->name = _name;
|
||||
// Suspiciously this also fails:
|
||||
//this->name = "foobar";
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwAddVarRW(
|
||||
const char *name,
|
||||
TwType type,
|
||||
void *var,
|
||||
const char *def,
|
||||
const bool record)
|
||||
{
|
||||
int ret = ::TwAddVarRW(this->bar,name,type,var,def);
|
||||
if(ret && record)
|
||||
{
|
||||
rw_items.push_back(ReTwRWItem(name,type,var));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwAddVarCB(
|
||||
const char *name,
|
||||
TwType type,
|
||||
TwSetVarCallback setCallback,
|
||||
TwGetVarCallback getCallback,
|
||||
void *clientData,
|
||||
const char *def,
|
||||
const bool record)
|
||||
{
|
||||
int ret =
|
||||
::TwAddVarCB(this->bar,name,type,setCallback,getCallback,clientData,def);
|
||||
if(ret && record)
|
||||
{
|
||||
cb_items.push_back(ReTwCBItem(name,type,setCallback,getCallback,clientData));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwAddVarRO(
|
||||
const char *name,
|
||||
TwType type,
|
||||
void *var,
|
||||
const char *def)
|
||||
{
|
||||
int ret = ::TwAddVarRO(this->bar,name,type,var,def);
|
||||
// Read only variables are not recorded
|
||||
//if(ret)
|
||||
//{
|
||||
// rw_items.push_back(ReTwRWItem(name,type,var));
|
||||
//}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwAddButton(
|
||||
const char *name,
|
||||
TwButtonCallback buttonCallback,
|
||||
void *clientData,
|
||||
const char *def)
|
||||
{
|
||||
int ret =
|
||||
::TwAddButton(this->bar,name,buttonCallback,clientData,def);
|
||||
// buttons are not recorded
|
||||
//if(ret)
|
||||
//{
|
||||
// cb_items.push_back(ReTwCBItem(name,type,setCallback,getCallback,clientData));
|
||||
//}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwSetParam(
|
||||
const char *varName,
|
||||
const char *paramName,
|
||||
TwParamValueType paramValueType,
|
||||
unsigned int inValueCount,
|
||||
const void *inValues)
|
||||
{
|
||||
// For now just pass these along
|
||||
return
|
||||
::TwSetParam(
|
||||
this->bar,
|
||||
varName,
|
||||
paramName,
|
||||
paramValueType,
|
||||
inValueCount,
|
||||
inValues);
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwGetParam(
|
||||
const char *varName,
|
||||
const char *paramName,
|
||||
TwParamValueType paramValueType,
|
||||
unsigned int outValueMaxCount,
|
||||
void *outValues)
|
||||
{
|
||||
return
|
||||
::TwGetParam(
|
||||
this->bar,
|
||||
varName,
|
||||
paramName,
|
||||
paramValueType,
|
||||
outValueMaxCount,
|
||||
outValues);
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwRefreshBar()
|
||||
{
|
||||
return ::TwRefreshBar(this->bar);
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::ReTwBar::TwTerminate()
|
||||
{
|
||||
//std::cout<<"TwTerminate"<<std::endl;
|
||||
int r = ::TwTerminate();
|
||||
//std::cout<<" "<<r<<std::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::anttweakbar::ReTwBar::save(const char *file_name)
|
||||
{
|
||||
FILE * fp;
|
||||
if(file_name == NULL)
|
||||
{
|
||||
fp = stdout;
|
||||
}else
|
||||
{
|
||||
fp = fopen(file_name,"w");
|
||||
}
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
printf("ERROR: not able to open %s for writing...\n",file_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Print all RW variables
|
||||
for(
|
||||
std::vector<ReTwRWItem>::iterator it = rw_items.begin();
|
||||
it != rw_items.end();
|
||||
it++)
|
||||
{
|
||||
std::string s = (*it).name;
|
||||
const char * name = s.c_str();
|
||||
TwType type = (*it).type;
|
||||
void * var = (*it).var;
|
||||
fprintf(fp,"%s: %s\n",
|
||||
name,
|
||||
get_value_as_string(var,type).c_str());
|
||||
}
|
||||
|
||||
char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
|
||||
// Print all CB variables
|
||||
for(
|
||||
std::vector<ReTwCBItem>::iterator it = cb_items.begin();
|
||||
it != cb_items.end();
|
||||
it++)
|
||||
{
|
||||
const char * name = it->name.c_str();
|
||||
TwType type = it->type;
|
||||
//TwSetVarCallback setCallback = it->setCallback;
|
||||
TwGetVarCallback getCallback = it->getCallback;
|
||||
void * clientData = it->clientData;
|
||||
// I'm not sure how to do what I want to do. getCallback needs to be sure
|
||||
// that it can write to var. So var needs to point to a valid and big
|
||||
// enough chunk of memory
|
||||
getCallback(var,clientData);
|
||||
fprintf(fp,"%s: %s\n",
|
||||
name,
|
||||
get_value_as_string(var,type).c_str());
|
||||
}
|
||||
|
||||
fprintf(fp,"\n");
|
||||
|
||||
if(file_name != NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
// everything succeeded
|
||||
return true;
|
||||
}
|
||||
|
||||
IGL_INLINE std::string igl::anttweakbar::ReTwBar::get_value_as_string(
|
||||
void * var,
|
||||
TwType type)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
switch(type)
|
||||
{
|
||||
case TW_TYPE_BOOLCPP:
|
||||
{
|
||||
sstr << "TW_TYPE_BOOLCPP" << " ";
|
||||
sstr << *(static_cast<bool*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4D:
|
||||
{
|
||||
sstr << "TW_TYPE_QUAT4D" << " ";
|
||||
// Q: Why does casting to double* work? shouldn't I have to cast to
|
||||
// double**?
|
||||
double * q = static_cast<double*>(var);
|
||||
sstr << std::setprecision(15) << q[0] << " " << q[1] << " " << q[2] << " " << q[3];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4F:
|
||||
{
|
||||
sstr << "TW_TYPE_QUAT4F" << " ";
|
||||
// Q: Why does casting to float* work? shouldn't I have to cast to
|
||||
// float**?
|
||||
float * q = static_cast<float*>(var);
|
||||
sstr << q[0] << " " << q[1] << " " << q[2] << " " << q[3];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_COLOR4F:
|
||||
{
|
||||
sstr << "TW_TYPE_COLOR4F" << " ";
|
||||
float * c = static_cast<float*>(var);
|
||||
sstr << c[0] << " " << c[1] << " " << c[2] << " " << c[3];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_COLOR3F:
|
||||
{
|
||||
sstr << "TW_TYPE_COLOR3F" << " ";
|
||||
float * c = static_cast<float*>(var);
|
||||
sstr << c[0] << " " << c[1] << " " << c[2];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_DIR3D:
|
||||
{
|
||||
sstr << "TW_TYPE_DIR3D" << " ";
|
||||
double * d = static_cast<double*>(var);
|
||||
sstr << std::setprecision(15) << d[0] << " " << d[1] << " " << d[2];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_DIR3F:
|
||||
{
|
||||
sstr << "TW_TYPE_DIR3F" << " ";
|
||||
float * d = static_cast<float*>(var);
|
||||
sstr << d[0] << " " << d[1] << " " << d[2];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_BOOL32:
|
||||
{
|
||||
sstr << "TW_TYPE_BOOL32" << " ";
|
||||
sstr << *(static_cast<int*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT8:
|
||||
{
|
||||
sstr << "TW_TYPE_UINT8" << " ";
|
||||
// Cast to int so that it's human readable
|
||||
sstr << (int)*(static_cast<unsigned char*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_INT32:
|
||||
{
|
||||
sstr << "TW_TYPE_INT32" << " ";
|
||||
sstr << *(static_cast<int*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT32:
|
||||
{
|
||||
sstr << "TW_TYPE_UINT32" << " ";
|
||||
sstr << *(static_cast<unsigned int*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_FLOAT:
|
||||
{
|
||||
sstr << "TW_TYPE_FLOAT" << " ";
|
||||
sstr << *(static_cast<float*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_DOUBLE:
|
||||
{
|
||||
sstr << "TW_TYPE_DOUBLE" << " ";
|
||||
sstr << std::setprecision(15) << *(static_cast<double*>(var));
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_STDSTRING:
|
||||
{
|
||||
sstr << "TW_TYPE_STDSTRING" << " ";
|
||||
std::string *destPtr = static_cast<std::string *>(var);
|
||||
sstr << destPtr->c_str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
using namespace std;
|
||||
std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::const_iterator iter =
|
||||
ReTw_custom_types.find(type);
|
||||
if(iter != ReTw_custom_types.end())
|
||||
{
|
||||
sstr << (*iter).second.first << " ";
|
||||
int enum_val = *(static_cast<int*>(var));
|
||||
// try find display name for enum value
|
||||
std::vector<TwEnumVal>::const_iterator eit = (*iter).second.second.begin();
|
||||
bool found = false;
|
||||
for(;eit<(*iter).second.second.end();eit++)
|
||||
{
|
||||
if(enum_val == eit->Value)
|
||||
{
|
||||
sstr << eit->Label;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
sstr << "ERROR_ENUM_VALUE_NOT_DEFINED";
|
||||
}
|
||||
}else
|
||||
{
|
||||
sstr << "ERROR_TYPE_NOT_SUPPORTED";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::anttweakbar::ReTwBar::load(const char *file_name)
|
||||
{
|
||||
FILE * fp;
|
||||
fp = fopen(file_name,"r");
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
printf("ERROR: not able to open %s for reading...\n",file_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// go through file line by line
|
||||
char line[REANTTWEAKBAR_MAX_LINE];
|
||||
bool still_comments;
|
||||
char name[REANTTWEAKBAR_MAX_WORD];
|
||||
char type_str[REANTTWEAKBAR_MAX_WORD];
|
||||
char value_str[REANTTWEAKBAR_MAX_WORD];
|
||||
|
||||
|
||||
// line number
|
||||
int j = 0;
|
||||
bool finished = false;
|
||||
while(true)
|
||||
{
|
||||
// Eat comments
|
||||
still_comments = true;
|
||||
while(still_comments)
|
||||
{
|
||||
if(fgets(line,REANTTWEAKBAR_MAX_LINE,fp) == NULL)
|
||||
{
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
// Blank lines and lines that begin with # are comments
|
||||
still_comments = (line[0] == '#' || line[0] == '\n');
|
||||
j++;
|
||||
}
|
||||
if(finished)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
sscanf(line,"%[^:]: %s %[^\n]",name,type_str,value_str);
|
||||
//printf("%s: %s %s\n",name, type_str,value_str);
|
||||
|
||||
TwType type;
|
||||
if(!type_from_string(type_str,type))
|
||||
{
|
||||
printf("ERROR: %s type not found... Skipping...\n",type_str);
|
||||
continue;
|
||||
}
|
||||
set_value_from_string(name,type,value_str);
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
// everything succeeded
|
||||
return true;
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::anttweakbar::ReTwBar::type_from_string(
|
||||
const char *type_str, TwType & type)
|
||||
{
|
||||
// first check default types
|
||||
for(int j = 0; j < RETW_NUM_DEFAULT_TYPE_STRINGS; j++)
|
||||
{
|
||||
if(strcmp(type_str,ReTwDefaultTypeStrings[j].type_str) == 0)
|
||||
{
|
||||
type = ReTwDefaultTypeStrings[j].type;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then check custom types
|
||||
std::map<
|
||||
TwType,std::pair<const char *,std::vector<TwEnumVal> >
|
||||
>::const_iterator iter =
|
||||
ReTw_custom_types.begin();
|
||||
for(;iter != ReTw_custom_types.end(); iter++)
|
||||
{
|
||||
if(strcmp((*iter).second.first,type_str)==0)
|
||||
{
|
||||
type = (*iter).first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool igl::anttweakbar::ReTwBar::set_value_from_string(
|
||||
const char * name,
|
||||
TwType type,
|
||||
const char * value_str)
|
||||
{
|
||||
void * value = NULL;
|
||||
// possible value slots
|
||||
int i;
|
||||
float v;
|
||||
double dv;
|
||||
float f[4];
|
||||
double d[4];
|
||||
bool b;
|
||||
unsigned int u;
|
||||
unsigned char uc;
|
||||
std::string s;
|
||||
|
||||
// First try to get value from default types
|
||||
switch(type)
|
||||
{
|
||||
case TW_TYPE_BOOLCPP:
|
||||
{
|
||||
int ib;
|
||||
if(sscanf(value_str," %d",&ib) == 1)
|
||||
{
|
||||
b = ib!=0;
|
||||
value = &b;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4D:
|
||||
//case TW_TYPE_COLOR4D:
|
||||
{
|
||||
if(sscanf(value_str," %lf %lf %lf %lf",&d[0],&d[1],&d[2],&d[3]) == 4)
|
||||
{
|
||||
value = &d;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4F:
|
||||
case TW_TYPE_COLOR4F:
|
||||
{
|
||||
if(sscanf(value_str," %f %f %f %f",&f[0],&f[1],&f[2],&f[3]) == 4)
|
||||
{
|
||||
value = &f;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//case TW_TYPE_COLOR3D:
|
||||
case TW_TYPE_DIR3D:
|
||||
{
|
||||
if(sscanf(value_str," %lf %lf %lf",&d[0],&d[1],&d[2]) == 3)
|
||||
{
|
||||
value = &d;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_COLOR3F:
|
||||
case TW_TYPE_DIR3F:
|
||||
{
|
||||
if(sscanf(value_str," %f %f %f",&f[0],&f[1],&f[2]) == 3)
|
||||
{
|
||||
value = &f;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT8:
|
||||
{
|
||||
if(sscanf(value_str," %d",&i) == 1)
|
||||
{
|
||||
// Cast to unsigned char
|
||||
uc = (unsigned char) i;
|
||||
value = &uc;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_BOOL32:
|
||||
case TW_TYPE_INT32:
|
||||
{
|
||||
if(sscanf(value_str," %d",&i) == 1)
|
||||
{
|
||||
value = &i;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT32:
|
||||
{
|
||||
if(sscanf(value_str," %u",&u) == 1)
|
||||
{
|
||||
value = &u;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_FLOAT:
|
||||
{
|
||||
if(sscanf(value_str," %f",&v) == 1)
|
||||
{
|
||||
value = &v;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_DOUBLE:
|
||||
{
|
||||
if(sscanf(value_str," %lf",&dv) == 1)
|
||||
{
|
||||
value = &dv;
|
||||
}else
|
||||
{
|
||||
printf("ERROR: Bad value format...\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_STDSTRING:
|
||||
{
|
||||
s = value_str;
|
||||
value = &s;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Try to find type in custom enum types
|
||||
std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::const_iterator iter =
|
||||
ReTw_custom_types.find(type);
|
||||
if(iter != ReTw_custom_types.end())
|
||||
{
|
||||
std::vector<TwEnumVal>::const_iterator eit = (*iter).second.second.begin();
|
||||
bool found = false;
|
||||
for(;eit<(*iter).second.second.end();eit++)
|
||||
{
|
||||
if(strcmp(value_str,eit->Label) == 0)
|
||||
{
|
||||
i = eit->Value;
|
||||
value = &i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
printf("ERROR_ENUM_VALUE_NOT_DEFINED");
|
||||
}
|
||||
}else
|
||||
{
|
||||
printf("ERROR_TYPE_NOT_SUPPORTED\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Find variable based on name
|
||||
// First look in RW items
|
||||
bool item_found = false;
|
||||
for(
|
||||
std::vector<ReTwRWItem>::iterator it = rw_items.begin();
|
||||
it != rw_items.end();
|
||||
it++)
|
||||
{
|
||||
if(it->name == name)
|
||||
{
|
||||
void * var = it->var;
|
||||
switch(type)
|
||||
{
|
||||
case TW_TYPE_BOOLCPP:
|
||||
{
|
||||
bool * bvar = static_cast<bool*>(var);
|
||||
bool * bvalue = static_cast<bool*>(value);
|
||||
*bvar = *bvalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4D:
|
||||
//case TW_TYPE_COLOR4D:
|
||||
{
|
||||
double * dvar = static_cast<double*>(var);
|
||||
double * dvalue = static_cast<double*>(value);
|
||||
dvar[0] = dvalue[0];
|
||||
dvar[1] = dvalue[1];
|
||||
dvar[2] = dvalue[2];
|
||||
dvar[3] = dvalue[3];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_QUAT4F:
|
||||
case TW_TYPE_COLOR4F:
|
||||
{
|
||||
float * fvar = static_cast<float*>(var);
|
||||
float * fvalue = static_cast<float*>(value);
|
||||
fvar[0] = fvalue[0];
|
||||
fvar[1] = fvalue[1];
|
||||
fvar[2] = fvalue[2];
|
||||
fvar[3] = fvalue[3];
|
||||
break;
|
||||
}
|
||||
//case TW_TYPE_COLOR3D:
|
||||
case TW_TYPE_DIR3D:
|
||||
{
|
||||
double * dvar = static_cast<double*>(var);
|
||||
double * dvalue = static_cast<double*>(value);
|
||||
dvar[0] = dvalue[0];
|
||||
dvar[1] = dvalue[1];
|
||||
dvar[2] = dvalue[2];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_COLOR3F:
|
||||
case TW_TYPE_DIR3F:
|
||||
{
|
||||
float * fvar = static_cast<float*>(var);
|
||||
float * fvalue = static_cast<float*>(value);
|
||||
fvar[0] = fvalue[0];
|
||||
fvar[1] = fvalue[1];
|
||||
fvar[2] = fvalue[2];
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT8:
|
||||
{
|
||||
unsigned char * ucvar = static_cast<unsigned char*>(var);
|
||||
unsigned char * ucvalue = static_cast<unsigned char*>(value);
|
||||
*ucvar = *ucvalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_BOOL32:
|
||||
case TW_TYPE_INT32:
|
||||
{
|
||||
int * ivar = static_cast<int*>(var);
|
||||
int * ivalue = static_cast<int*>(value);
|
||||
*ivar = *ivalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_UINT32:
|
||||
{
|
||||
unsigned int * uvar = static_cast<unsigned int*>(var);
|
||||
unsigned int * uvalue = static_cast<unsigned int*>(value);
|
||||
*uvar = *uvalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_FLOAT:
|
||||
{
|
||||
float * fvar = static_cast<float*>(var);
|
||||
float * fvalue = static_cast<float*>(value);
|
||||
*fvar = *fvalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_DOUBLE:
|
||||
{
|
||||
double * dvar = static_cast<double*>(var);
|
||||
double * fvalue = static_cast<double*>(value);
|
||||
*dvar = *fvalue;
|
||||
break;
|
||||
}
|
||||
case TW_TYPE_STDSTRING:
|
||||
{
|
||||
std::string * svar = static_cast<std::string*>(var);
|
||||
std::string * svalue = static_cast<std::string*>(value);
|
||||
*svar = *svalue;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Try to find type in custom enum types
|
||||
std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::iterator iter =
|
||||
ReTw_custom_types.find(type);
|
||||
if(iter != ReTw_custom_types.end())
|
||||
{
|
||||
int * ivar = static_cast<int*>(var);
|
||||
std::vector<TwEnumVal>::iterator eit = (*iter).second.second.begin();
|
||||
bool found = false;
|
||||
for(;eit<(*iter).second.second.end();eit++)
|
||||
{
|
||||
if(strcmp(value_str,eit->Label) == 0)
|
||||
{
|
||||
*ivar = eit->Value;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
printf("ERROR_ENUM_VALUE_NOT_DEFINED");
|
||||
}
|
||||
}else
|
||||
{
|
||||
printf("ERROR_TYPE_NOT_SUPPORTED\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
item_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try looking in CB items
|
||||
if(!item_found)
|
||||
{
|
||||
for(
|
||||
std::vector<ReTwCBItem>::iterator it = cb_items.begin();
|
||||
it != cb_items.end();
|
||||
it++)
|
||||
{
|
||||
if(it->name==name)
|
||||
{
|
||||
it->setCallback(value,it->clientData);
|
||||
item_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!item_found)
|
||||
{
|
||||
printf("ERROR: item '%s' not found\n",name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
IGL_INLINE const std::vector<igl::anttweakbar::ReTwRWItem> &
|
||||
igl::anttweakbar::ReTwBar::get_rw_items()
|
||||
{
|
||||
return rw_items;
|
||||
}
|
||||
|
||||
IGL_INLINE const std::vector<igl::anttweakbar::ReTwCBItem> &
|
||||
igl::anttweakbar::ReTwBar::get_cb_items()
|
||||
{
|
||||
return cb_items;
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_ANTTWEAKBAR_REANTTWEAKBAR_H
|
||||
#define IGL_ANTTWEAKBAR_REANTTWEAKBAR_H
|
||||
#include "../igl_inline.h"
|
||||
// ReAntTweakBar is a minimal wrapper for the AntTweakBar library that allows
|
||||
// "bars" to be saved and load from disk. Changing your existing app that uses
|
||||
// AntTweakBar to use ReAntTweakBar is trivial.
|
||||
//
|
||||
// Many (but not all) variable types are supported. I'll try to keep track them
|
||||
// here:
|
||||
// TW_TYPE_BOOLCPP
|
||||
// TW_TYPE_QUAT4F
|
||||
// TW_TYPE_QUAT4D
|
||||
// TW_TYPE_COLOR4F
|
||||
// TW_TYPE_COLOR4D
|
||||
// TW_TYPE_COLOR3F
|
||||
// TW_TYPE_DIR3F
|
||||
// TW_TYPE_DIR3D
|
||||
// TW_TYPE_BOOL32
|
||||
// TW_TYPE_INT32
|
||||
// TW_TYPE_UINT32
|
||||
// TW_TYPE_FLOAT
|
||||
// TW_TYPE_DOUBLE
|
||||
// TW_TYPE_UINT8
|
||||
// and
|
||||
// custom TwTypes made with TwDefineEnum
|
||||
//
|
||||
// I'm working on adding the rest on an as-needed basis. Adding a new type only
|
||||
// requires changes in a few places...
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// This allows the user to have a non-global, static installation of
|
||||
// AntTweakBar
|
||||
#include <AntTweakBar.h>
|
||||
// Instead of including AntTweakBar.h, just define the necessary types
|
||||
// Types used:
|
||||
// - TwType
|
||||
// - TwEnumVal
|
||||
// - TwSetVarCallback
|
||||
// - TwGetVarCallback
|
||||
// - TwBar
|
||||
// - TwButtonCallback
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#define REANTTWEAKBAR_MAX_CB_VAR_SIZE 1000
|
||||
// Max line size for reading files
|
||||
#define REANTTWEAKBAR_MAX_LINE 1000
|
||||
#define REANTTWEAKBAR_MAX_WORD 100
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace anttweakbar
|
||||
{
|
||||
TwType ReTwDefineEnum(
|
||||
const char *name,
|
||||
const TwEnumVal *enumValues,
|
||||
unsigned int nbValues);
|
||||
TwType ReTwDefineEnumFromString(const char * name,const char * enumString);
|
||||
|
||||
struct ReTwRWItem
|
||||
{
|
||||
//const char * name;
|
||||
std::string name;
|
||||
TwType type;
|
||||
void * var;
|
||||
// Default constructor
|
||||
IGL_INLINE ReTwRWItem(
|
||||
const std::string _name,
|
||||
TwType _type,
|
||||
void *_var):
|
||||
name(_name),
|
||||
type(_type),
|
||||
var(_var)
|
||||
{
|
||||
}
|
||||
// Shallow copy constructor
|
||||
// I solemnly swear it's OK to copy var this way
|
||||
// Q: Is it really?
|
||||
IGL_INLINE ReTwRWItem(const ReTwRWItem & that):
|
||||
name(that.name),
|
||||
type(that.type),
|
||||
var(that.var)
|
||||
{
|
||||
}
|
||||
// Shallow assignment
|
||||
// I solemnly swear it's OK to copy var this way
|
||||
IGL_INLINE ReTwRWItem & operator=(const ReTwRWItem & that)
|
||||
{
|
||||
if(this != &that)
|
||||
{
|
||||
this->name = that.name;
|
||||
this->type = that.type;
|
||||
this->var = that.var;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct ReTwCBItem
|
||||
{
|
||||
//const char * name;
|
||||
std::string name;
|
||||
TwType type;
|
||||
TwSetVarCallback setCallback;
|
||||
TwGetVarCallback getCallback;
|
||||
void * clientData;
|
||||
// Default constructor
|
||||
IGL_INLINE ReTwCBItem(
|
||||
const std::string _name,
|
||||
TwType _type,
|
||||
TwSetVarCallback _setCallback,
|
||||
TwGetVarCallback _getCallback,
|
||||
void * _clientData):
|
||||
name(_name),
|
||||
type(_type),
|
||||
setCallback(_setCallback),
|
||||
getCallback(_getCallback),
|
||||
clientData(_clientData)
|
||||
{
|
||||
}
|
||||
// Shallow copy
|
||||
// I solemnly swear it's OK to copy clientData this way
|
||||
IGL_INLINE ReTwCBItem(const ReTwCBItem & that):
|
||||
name(that.name),
|
||||
type(that.type),
|
||||
setCallback(that.setCallback),
|
||||
getCallback(that.getCallback),
|
||||
clientData(that.clientData)
|
||||
{
|
||||
}
|
||||
// Shallow assignment
|
||||
// I solemnly swear it's OK to copy clientData this way
|
||||
IGL_INLINE ReTwCBItem & operator=(const ReTwCBItem & that)
|
||||
{
|
||||
if(this != &that)
|
||||
{
|
||||
name = that.name;
|
||||
type = that.type;
|
||||
setCallback = that.setCallback;
|
||||
getCallback = that.getCallback;
|
||||
clientData = that.clientData;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ReTwBar
|
||||
{
|
||||
// VARIABLES
|
||||
// Should be private, but seeing as I'm not going to implement all of the
|
||||
// AntTweakBar public functions right away, I'll expose this so that at
|
||||
// anytime AntTweakBar functions can be called directly on the bar
|
||||
public:
|
||||
TwBar * bar;
|
||||
std::string name;
|
||||
protected:
|
||||
std::vector<ReTwRWItem> rw_items;
|
||||
std::vector<ReTwCBItem> cb_items;
|
||||
public:
|
||||
// Default constructor with explicit initialization
|
||||
IGL_INLINE ReTwBar();
|
||||
private:
|
||||
// Copy constructor does shallow copy
|
||||
IGL_INLINE ReTwBar(const ReTwBar & that);
|
||||
// Assignment operator does shallow assignment
|
||||
IGL_INLINE ReTwBar &operator=(const ReTwBar & that);
|
||||
|
||||
// WRAPPERS FOR ANTTWEAKBAR FUNCTIONS
|
||||
public:
|
||||
IGL_INLINE void TwNewBar(const char *_name);
|
||||
IGL_INLINE int TwAddVarRW(
|
||||
const char *name,
|
||||
TwType type,
|
||||
void *var,
|
||||
const char *def,
|
||||
const bool record=true);
|
||||
IGL_INLINE int TwAddVarCB(
|
||||
const char *name,
|
||||
TwType type,
|
||||
TwSetVarCallback setCallback,
|
||||
TwGetVarCallback getCallback,
|
||||
void *clientData,
|
||||
const char *def,
|
||||
const bool record=true);
|
||||
// Wrappers for convenience (not recorded, just passed on)
|
||||
IGL_INLINE int TwAddVarRO(const char *name, TwType type, void *var, const char *def);
|
||||
IGL_INLINE int TwAddButton(
|
||||
const char *name,
|
||||
TwButtonCallback buttonCallback,
|
||||
void *clientData,
|
||||
const char *def);
|
||||
IGL_INLINE int TwSetParam(
|
||||
const char *varName,
|
||||
const char *paramName,
|
||||
TwParamValueType paramValueType,
|
||||
unsigned int inValueCount,
|
||||
const void *inValues);
|
||||
IGL_INLINE int TwGetParam(
|
||||
const char *varName,
|
||||
const char *paramName,
|
||||
TwParamValueType paramValueType,
|
||||
unsigned int outValueMaxCount,
|
||||
void *outValues);
|
||||
IGL_INLINE int TwRefreshBar();
|
||||
IGL_INLINE int TwTerminate();
|
||||
|
||||
|
||||
// IO FUNCTIONS
|
||||
public:
|
||||
// Save current items to file
|
||||
// Input:
|
||||
// file_name name of file to save data to, can be null which means print
|
||||
// to stdout
|
||||
// Return:
|
||||
// true only if there were no (fatal) errors
|
||||
IGL_INLINE bool save(const char *file_name);
|
||||
std::string get_value_as_string(
|
||||
void * var,
|
||||
TwType type);
|
||||
// Load into current items from file
|
||||
// Input:
|
||||
// file_name name of input file to load
|
||||
// Return:
|
||||
// true only if there were no (fatal) errors
|
||||
IGL_INLINE bool load(const char *file_name);
|
||||
// Get TwType from string
|
||||
// Input
|
||||
// type_str string of type
|
||||
// Output
|
||||
// type TwType converted from string
|
||||
// Returns
|
||||
// true only if string matched a valid type
|
||||
IGL_INLINE bool type_from_string(const char *type_str, TwType & type);
|
||||
// I realize that I mix std::string and const char * all over the place.
|
||||
// What can you do...
|
||||
IGL_INLINE bool set_value_from_string(
|
||||
const char * name,
|
||||
TwType type,
|
||||
const char * value_str);
|
||||
IGL_INLINE const std::vector<ReTwRWItem> & get_rw_items();
|
||||
IGL_INLINE const std::vector<ReTwCBItem> & get_cb_items();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// List of TwBar functions
|
||||
//TW_API TwBar * TW_CALL TwNewBar(const char *barName);
|
||||
//TW_API int TW_CALL TwDeleteBar(TwBar *bar);
|
||||
//TW_API int TW_CALL TwDeleteAllBars();
|
||||
//TW_API int TW_CALL TwSetTopBar(const TwBar *bar);
|
||||
//TW_API TwBar * TW_CALL TwGetTopBar();
|
||||
//TW_API int TW_CALL TwSetBottomBar(const TwBar *bar);
|
||||
//TW_API TwBar * TW_CALL TwGetBottomBar();
|
||||
//TW_API const char * TW_CALL TwGetBarName(TwBar *bar);
|
||||
//TW_API int TW_CALL TwGetBarCount();
|
||||
//TW_API TwBar * TW_CALL TwGetBarByIndex(int barIndex);
|
||||
//TW_API TwBar * TW_CALL TwGetBarByName(const char *barName);
|
||||
//TW_API int TW_CALL TwRefreshBar(TwBar *bar);
|
||||
//TW_API int TW_CALL TwTerminate();
|
||||
//
|
||||
//TW_API int TW_CALL TwAddVarRW(TwBar *bar, const char *name, TwType type, void *var, const char *def);
|
||||
//TW_API int TW_CALL TwAddVarRO(TwBar *bar, const char *name, TwType type, const void *var, const char *def);
|
||||
//TW_API int TW_CALL TwAddVarCB(TwBar *bar, const char *name, TwType type, TwSetVarCallback setCallback, TwGetVarCallback getCallback, void *clientData, const char *def);
|
||||
//TW_API int TW_CALL TwAddButton(TwBar *bar, const char *name, TwButtonCallback callback, void *clientData, const char *def);
|
||||
//TW_API int TW_CALL TwAddSeparator(TwBar *bar, const char *name, const char *def);
|
||||
//TW_API int TW_CALL TwRemoveVar(TwBar *bar, const char *name);
|
||||
//TW_API int TW_CALL TwRemoveAllVars(TwBar *bar);
|
||||
|
||||
// Until AntTweakBar dependency folder exists, this is header-only
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "ReAntTweakBar.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,81 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "cocoa_key_to_anttweakbar_key.h"
|
||||
|
||||
#include <AntTweakBar.h>
|
||||
|
||||
IGL_INLINE int igl::anttweakbar::cocoa_key_to_anttweakbar_key(int key)
|
||||
{
|
||||
// I've left commented the AntTweakBar key codes that correspond to keys I
|
||||
// don't have on my keyboard. Please fill this in if you have those keys
|
||||
switch(key)
|
||||
{
|
||||
case 127:
|
||||
return TW_KEY_BACKSPACE;
|
||||
case 9:
|
||||
return TW_KEY_TAB;
|
||||
//TW_KEY_CLEAR = 0x0c,
|
||||
case 3://ENTER
|
||||
case 13:
|
||||
return TW_KEY_RETURN;
|
||||
case 27:
|
||||
return TW_KEY_ESCAPE;
|
||||
case 32:
|
||||
return TW_KEY_SPACE;
|
||||
// IN A GLUT APP 40 is (
|
||||
//case 40:
|
||||
case 63272:
|
||||
return TW_KEY_DELETE;
|
||||
case 63232:
|
||||
return TW_KEY_UP;
|
||||
case 63233:
|
||||
return TW_KEY_DOWN;
|
||||
case 63235:
|
||||
return TW_KEY_RIGHT;
|
||||
case 63234:
|
||||
return TW_KEY_LEFT;
|
||||
//TW_KEY_INSERT,
|
||||
//TW_KEY_HOME,
|
||||
//TW_KEY_END,
|
||||
//TW_KEY_PAGE_UP,
|
||||
//TW_KEY_PAGE_DOWN,
|
||||
case 63236:
|
||||
return TW_KEY_F1;
|
||||
case 63237:
|
||||
return TW_KEY_F2;
|
||||
case 63238:
|
||||
return TW_KEY_F3;
|
||||
case 63239:
|
||||
return TW_KEY_F4;
|
||||
case 63240:
|
||||
return TW_KEY_F5;
|
||||
case 63241:
|
||||
return TW_KEY_F6;
|
||||
case 63242:
|
||||
return TW_KEY_F7;
|
||||
case 63243:
|
||||
return TW_KEY_F8;
|
||||
case 63244:
|
||||
return TW_KEY_F9;
|
||||
case 63245:
|
||||
return TW_KEY_F10;
|
||||
case 63246:
|
||||
return TW_KEY_F11;
|
||||
case 63247:
|
||||
return TW_KEY_F12;
|
||||
case 63248:
|
||||
return TW_KEY_F13;
|
||||
case 63249:
|
||||
return TW_KEY_F14;
|
||||
case 63250:
|
||||
return TW_KEY_F15;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_ANTTWEAKBAR_COCOA_KEY_TO_ANTTWEAKBAR_KEY_H
|
||||
#define IGL_ANTTWEAKBAR_COCOA_KEY_TO_ANTTWEAKBAR_KEY_H
|
||||
#include "../igl_inline.h"
|
||||
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace anttweakbar
|
||||
{
|
||||
// Convert an unsigned char (like that from Cocoa apps) to AntTweakBar key
|
||||
// code.
|
||||
// See also: TranslateKey() in TwMgr.cpp in AntTweakBar source
|
||||
// Inputs:
|
||||
// key unsigned char key from keyboard
|
||||
// Returns int of new key code
|
||||
IGL_INLINE int cocoa_key_to_anttweakbar_key(int key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "cocoa_key_to_anttweakbar_key.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,12 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "avg_edge_length.h"
|
||||
#include "edges.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -14,20 +15,19 @@ IGL_INLINE double igl::avg_edge_length(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F)
|
||||
{
|
||||
double avg = 0;
|
||||
long int count = 0;
|
||||
typedef typename DerivedF::Scalar Index;
|
||||
Eigen::Matrix<Index, Eigen::Dynamic, 2> E;
|
||||
|
||||
// Augh. Technically this is double counting interior edges...
|
||||
for (unsigned i=0;i<F.rows();++i)
|
||||
igl::edges(F, E);
|
||||
|
||||
double avg = 0;
|
||||
|
||||
for (unsigned i=0;i<E.rows();++i)
|
||||
{
|
||||
for (unsigned j=0;j<F.cols();++j)
|
||||
{
|
||||
++count;
|
||||
avg += (V.row(F(i,j)) - V.row(F(i,(j+1)%F.cols()))).norm();
|
||||
}
|
||||
avg += (V.row(E(i,0)) - V.row(E(i,1))).norm();
|
||||
}
|
||||
|
||||
return avg / (double) count;
|
||||
return avg / (double) E.rows();
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_AVERAGEEDGELENGTH_H
|
||||
#define IGL_AVERAGEEDGELENGTH_H
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
namespace igl
|
||||
{
|
||||
// Compute the average edge length for the given triangle mesh
|
||||
// Templates:
|
||||
|
||||
+12
-11
@@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "cat.h"
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
#include <unsupported/Eigen/SparseExtra>
|
||||
|
||||
|
||||
// Sparse matrices need to be handled carefully. Because C++ does not
|
||||
// Sparse matrices need to be handled carefully. Because C++ does not
|
||||
// Template:
|
||||
// Scalar sparse matrix scalar type, e.g. double
|
||||
template <typename Scalar>
|
||||
IGL_INLINE void igl::cat(
|
||||
const int dim,
|
||||
const Eigen::SparseMatrix<Scalar> & A,
|
||||
const Eigen::SparseMatrix<Scalar> & B,
|
||||
const int dim,
|
||||
const Eigen::SparseMatrix<Scalar> & A,
|
||||
const Eigen::SparseMatrix<Scalar> & B,
|
||||
Eigen::SparseMatrix<Scalar> & C)
|
||||
{
|
||||
|
||||
@@ -108,13 +108,13 @@ IGL_INLINE void igl::cat(
|
||||
|
||||
}
|
||||
|
||||
C = SparseMatrix<Scalar>(
|
||||
C = SparseMatrix<Scalar>(
|
||||
dim == 1 ? A.rows()+B.rows() : A.rows(),
|
||||
dim == 1 ? A.cols() : A.cols()+B.cols());
|
||||
C.reserve(A.nonZeros() + B.nonZeros());
|
||||
C.setFromTriplets(CIJV.begin(),CIJV.end());
|
||||
#else
|
||||
C = SparseMatrix<Scalar>(
|
||||
C = SparseMatrix<Scalar>(
|
||||
dim == 1 ? A.rows()+B.rows() : A.rows(),
|
||||
dim == 1 ? A.cols() : A.cols()+B.cols());
|
||||
Eigen::VectorXi per_col = Eigen::VectorXi::Zero(C.cols());
|
||||
@@ -189,7 +189,7 @@ IGL_INLINE void igl::cat(
|
||||
template <typename Derived, class MatC>
|
||||
IGL_INLINE void igl::cat(
|
||||
const int dim,
|
||||
const Eigen::MatrixBase<Derived> & A,
|
||||
const Eigen::MatrixBase<Derived> & A,
|
||||
const Eigen::MatrixBase<Derived> & B,
|
||||
MatC & C)
|
||||
{
|
||||
@@ -264,4 +264,5 @@ template Eigen::Matrix<int, -1, 1, 0, -1, 1> igl::cat<Eigen::Matrix<int, -1, 1,
|
||||
template Eigen::Matrix<double, -1, 1, 0, -1, 1> igl::cat<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(int, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&);
|
||||
template void igl::cat<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(int, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
|
||||
template void igl::cat<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
|
||||
template void igl::cat<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
|
||||
#endif
|
||||
|
||||
@@ -64,4 +64,5 @@ IGL_INLINE void igl::centroid(
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
|
||||
#endif
|
||||
|
||||
@@ -86,35 +86,42 @@ namespace igl {
|
||||
|
||||
std::deque<int> d;
|
||||
|
||||
d.push_back(0);
|
||||
mark(0) = true;
|
||||
|
||||
while (!d.empty())
|
||||
while (!mark.all()) // Stop until all vertices are marked
|
||||
{
|
||||
int f0 = d.at(0);
|
||||
d.pop_front();
|
||||
for (int k=0; k<3; k++)
|
||||
int unmarked = 0;
|
||||
while (mark(unmarked))
|
||||
unmarked++;
|
||||
|
||||
d.push_back(unmarked);
|
||||
mark(unmarked) = true;
|
||||
|
||||
while (!d.empty())
|
||||
{
|
||||
int f1 = TT(f0,k);
|
||||
if (f1==-1) continue;
|
||||
if (mark(f1)) continue;
|
||||
int f0 = d.at(0);
|
||||
d.pop_front();
|
||||
for (int k=0; k<3; k++)
|
||||
{
|
||||
int f1 = TT(f0,k);
|
||||
if (f1==-1) continue;
|
||||
if (mark(f1)) continue;
|
||||
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1out.row(f0);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1out.row(f1);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0 = N.row(f0);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1 = N.row(f1);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1out.row(f0);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1out.row(f1);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0 = N.row(f0);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1 = N.row(f1);
|
||||
|
||||
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0Rot = igl::rotation_matrix_from_directions(n0, n1)*dir0;
|
||||
dir0Rot.normalize();
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> targD = K_PI_new(dir1,dir0Rot,n1);
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0Rot = igl::rotation_matrix_from_directions(n0, n1)*dir0;
|
||||
dir0Rot.normalize();
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3, 1> targD = K_PI_new(dir1,dir0Rot,n1);
|
||||
|
||||
PD1out.row(f1) = targD;
|
||||
PD2out.row(f1) = n1.cross(targD).normalized();
|
||||
PD1out.row(f1) = targD;
|
||||
PD2out.row(f1) = n1.cross(targD).normalized();
|
||||
|
||||
mark(f1) = true;
|
||||
d.push_back(f1);
|
||||
mark(f1) = true;
|
||||
d.push_back(f1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,44 +33,45 @@ extern const int edgeTable[256];
|
||||
extern const int triTable[256][2][17];
|
||||
extern const int polyTable[8][16];
|
||||
|
||||
struct EdgeKey
|
||||
{
|
||||
EdgeKey(unsigned i0, unsigned i1) : i0_(i0), i1_(i1) {}
|
||||
|
||||
bool operator==(const EdgeKey& _rhs) const
|
||||
{
|
||||
return i0_ == _rhs.i0_ && i1_ == _rhs.i1_;
|
||||
}
|
||||
|
||||
unsigned i0_, i1_;
|
||||
};
|
||||
|
||||
struct EdgeHash
|
||||
{
|
||||
std::size_t operator()(const EdgeKey& key) const {
|
||||
std::size_t seed = 0;
|
||||
seed ^= key.i0_ + 0x9e3779b9 + (seed<<6) + (seed>>2); // Copied from boost::hash_combine
|
||||
seed ^= key.i1_ + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
return std::hash<std::size_t>()(seed);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Derivedvalues, typename Derivedpoints,typename Derivedvertices, typename DerivedF>
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedIndices, typename DerivedFaces>
|
||||
class MarchingCubes
|
||||
{
|
||||
struct EdgeKey
|
||||
{
|
||||
EdgeKey(unsigned i0, unsigned i1) : i0_(i0), i1_(i1) {}
|
||||
|
||||
bool operator==(const EdgeKey& _rhs) const
|
||||
{
|
||||
return i0_ == _rhs.i0_ && i1_ == _rhs.i1_;
|
||||
}
|
||||
|
||||
unsigned i0_, i1_;
|
||||
};
|
||||
|
||||
struct EdgeHash
|
||||
{
|
||||
std::size_t operator()(const EdgeKey& key) const {
|
||||
std::size_t seed = 0;
|
||||
seed ^= key.i0_ + 0x9e3779b9 + (seed<<6) + (seed>>2); // Copied from boost::hash_combine
|
||||
seed ^= key.i1_ + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
return std::hash<std::size_t>()(seed);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<EdgeKey, unsigned, EdgeHash> MyMap;
|
||||
typedef typename MyMap::const_iterator MyMapIterator;
|
||||
|
||||
public:
|
||||
MarchingCubes(
|
||||
const Eigen::PlainObjectBase<Derivedvalues> &values,
|
||||
const Eigen::PlainObjectBase<Derivedpoints> &points,
|
||||
// Dense index grid version
|
||||
MarchingCubes(const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const unsigned x_res,
|
||||
const unsigned y_res,
|
||||
const unsigned z_res,
|
||||
Eigen::PlainObjectBase<Derivedvertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedF> &faces)
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
assert(values.cols() == 1);
|
||||
assert(points.cols() == 3);
|
||||
@@ -101,7 +102,7 @@ public:
|
||||
{
|
||||
|
||||
unsigned corner[8];
|
||||
typename DerivedF::Scalar samples[12];
|
||||
typename DerivedFaces::Scalar samples[12];
|
||||
unsigned char cubetype(0);
|
||||
unsigned int i;
|
||||
|
||||
@@ -126,7 +127,7 @@ public:
|
||||
|
||||
// determine cube type
|
||||
for (i=0; i<8; ++i)
|
||||
if (values(corner[i]) > 0.0)
|
||||
if (values(corner[i]) > isovalue)
|
||||
cubetype |= (1<<i);
|
||||
|
||||
|
||||
@@ -182,77 +183,220 @@ public:
|
||||
vertices.conservativeResize(num_vertices, Eigen::NoChange);
|
||||
faces.conservativeResize(num_faces, Eigen::NoChange);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static typename DerivedF::Scalar add_vertex(const Eigen::PlainObjectBase<Derivedvalues> &values,
|
||||
const Eigen::PlainObjectBase<Derivedpoints> &points,
|
||||
unsigned int i0,
|
||||
unsigned int i1,
|
||||
Eigen::PlainObjectBase<Derivedvertices> &vertices,
|
||||
int &num_vertices,
|
||||
MyMap &edge2vertex)
|
||||
// Sparse index grid version
|
||||
MarchingCubes(const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const Eigen::MatrixBase<DerivedIndices> &cubes,
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
assert(values.cols() == 1);
|
||||
assert(points.cols() == 3);
|
||||
assert(cubes.cols() == 8);
|
||||
|
||||
if(cubes.rows() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
faces.resize(10000,3);
|
||||
int num_faces = 0;
|
||||
|
||||
vertices.resize(10000,3);
|
||||
int num_vertices = 0;
|
||||
|
||||
|
||||
unsigned n_cubes = cubes.rows();
|
||||
|
||||
for (unsigned cube_it =0 ; cube_it < n_cubes; ++cube_it)
|
||||
{
|
||||
typedef Eigen::Matrix<typename DerivedIndices::Scalar, 1, 8> CubeIndexVector;
|
||||
typedef typename DerivedFaces::Scalar SampleScalar;
|
||||
|
||||
CubeIndexVector cube = cubes.row(cube_it);
|
||||
SampleScalar samples[12];
|
||||
unsigned char cubetype(0);
|
||||
|
||||
// determine cube type
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
if (values[cube[i]] > isovalue)
|
||||
{
|
||||
cubetype |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// trivial reject ?
|
||||
if (cubetype == 0 || cubetype == 255)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// compute samples on cube's edges
|
||||
if (edgeTable[cubetype]&1)
|
||||
samples[0] = add_vertex(values, points, cube[0], cube[1], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&2)
|
||||
samples[1] = add_vertex(values, points, cube[1], cube[2], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&4)
|
||||
samples[2] = add_vertex(values, points, cube[3], cube[2], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&8)
|
||||
samples[3] = add_vertex(values, points, cube[0], cube[3], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&16)
|
||||
samples[4] = add_vertex(values, points, cube[4], cube[5], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&32)
|
||||
samples[5] = add_vertex(values, points, cube[5], cube[6], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&64)
|
||||
samples[6] = add_vertex(values, points, cube[7], cube[6], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&128)
|
||||
samples[7] = add_vertex(values, points, cube[4], cube[7], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&256)
|
||||
samples[8] = add_vertex(values, points, cube[0], cube[4], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&512)
|
||||
samples[9] = add_vertex(values, points, cube[1], cube[5], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&1024)
|
||||
samples[10] = add_vertex(values, points, cube[2], cube[6], vertices, num_vertices, edge2vertex);
|
||||
if (edgeTable[cubetype]&2048)
|
||||
samples[11] = add_vertex(values, points, cube[3], cube[7], vertices, num_vertices, edge2vertex);
|
||||
|
||||
// connect samples by triangles
|
||||
for (int i=0; triTable[cubetype][0][i] != -1; i+=3 )
|
||||
{
|
||||
num_faces++;
|
||||
if (num_faces > faces.rows())
|
||||
{
|
||||
faces.conservativeResize(faces.rows()+10000, Eigen::NoChange);
|
||||
}
|
||||
faces.row(num_faces-1) <<
|
||||
samples[triTable[cubetype][0][i ]],
|
||||
samples[triTable[cubetype][0][i+1]],
|
||||
samples[triTable[cubetype][0][i+2]];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vertices.conservativeResize(num_vertices, Eigen::NoChange);
|
||||
faces.conservativeResize(num_faces, Eigen::NoChange);
|
||||
|
||||
}
|
||||
|
||||
static typename DerivedFaces::Scalar add_vertex(const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
unsigned int i0,
|
||||
unsigned int i1,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
int &num_vertices,
|
||||
MyMap &edge2vertex)
|
||||
{
|
||||
// find vertex if it has been computed already
|
||||
MyMapIterator it = edge2vertex.find(EdgeKey(i0, i1));
|
||||
if (it != edge2vertex.end())
|
||||
{
|
||||
return it->second;
|
||||
;
|
||||
}
|
||||
|
||||
// generate new vertex
|
||||
const Eigen::Matrix<typename Derivedpoints::Scalar, 1, 3> & p0 = points.row(i0);
|
||||
const Eigen::Matrix<typename Derivedpoints::Scalar, 1, 3> & p1 = points.row(i1);
|
||||
|
||||
typename Derivedvalues::Scalar s0 = fabs(values(i0));
|
||||
typename Derivedvalues::Scalar s1 = fabs(values(i1));
|
||||
typename Derivedvalues::Scalar t = s0 / (s0+s1);
|
||||
const Eigen::Matrix<typename DerivedPoints::Scalar, 1, 3> & p0 = points.row(i0);
|
||||
const Eigen::Matrix<typename DerivedPoints::Scalar, 1, 3> & p1 = points.row(i1);
|
||||
|
||||
typename DerivedValues::Scalar s0 = fabs(values[i0]);
|
||||
typename DerivedValues::Scalar s1 = fabs(values[i1]);
|
||||
typename DerivedValues::Scalar t = s0 / (s0+s1);
|
||||
|
||||
num_vertices++;
|
||||
if (num_vertices > vertices.rows())
|
||||
{
|
||||
vertices.conservativeResize(vertices.rows()+10000, Eigen::NoChange);
|
||||
}
|
||||
|
||||
// Linear interpolation based on linearly interpolating values
|
||||
vertices.row(num_vertices-1) = ((1.0f-t)*p0 + t*p1).template cast<typename Derivedvertices::Scalar>();
|
||||
vertices.row(num_vertices-1) = ((1.0f-t)*p0 + t*p1).template cast<typename DerivedVertices::Scalar>();
|
||||
edge2vertex[EdgeKey(i0, i1)] = num_vertices-1;
|
||||
|
||||
return num_vertices-1;
|
||||
}
|
||||
;
|
||||
|
||||
// maps an edge to the sample vertex generated on it
|
||||
MyMap edge2vertex;
|
||||
};
|
||||
|
||||
|
||||
template <typename Derivedvalues, typename Derivedpoints, typename Derivedvertices, typename DerivedF>
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedFaces>
|
||||
IGL_INLINE void igl::copyleft::marching_cubes(
|
||||
const Eigen::PlainObjectBase<Derivedvalues> &values,
|
||||
const Eigen::PlainObjectBase<Derivedpoints> &points,
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const unsigned x_res,
|
||||
const unsigned y_res,
|
||||
const unsigned z_res,
|
||||
Eigen::PlainObjectBase<Derivedvertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedF> &faces)
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
MarchingCubes<Derivedvalues, Derivedpoints, Derivedvertices, DerivedF> mc(values,
|
||||
points,
|
||||
x_res,
|
||||
y_res,
|
||||
z_res,
|
||||
vertices,
|
||||
faces);
|
||||
typedef Eigen::MatrixXi Shim; /* DerivedIndices shim type is unused in this instantiation*/
|
||||
MarchingCubes<DerivedValues, DerivedPoints, DerivedVertices, Shim, DerivedFaces>
|
||||
mc(values, points, x_res, y_res, z_res, isovalue, vertices, faces);
|
||||
}
|
||||
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedFaces>
|
||||
IGL_INLINE void igl::copyleft::marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const unsigned x_res,
|
||||
const unsigned y_res,
|
||||
const unsigned z_res,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
typedef Eigen::MatrixXi Shim; /* DerivedIndices shim type is unused in this instantiation*/
|
||||
MarchingCubes<DerivedValues, DerivedPoints, DerivedVertices, Shim, DerivedFaces>
|
||||
mc(values, points, x_res, y_res, z_res, 0.0 /*isovalue*/, vertices, faces);
|
||||
}
|
||||
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedIndices, typename DerivedFaces>
|
||||
IGL_INLINE void igl::copyleft::marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues>& values,
|
||||
const Eigen::MatrixBase<DerivedPoints>& points,
|
||||
const Eigen::MatrixBase<DerivedIndices>& indices,
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices>& vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
MarchingCubes<DerivedValues, DerivedPoints, DerivedVertices, DerivedIndices, DerivedFaces> mc(values, points, indices, isovalue, vertices, faces);
|
||||
}
|
||||
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedIndices, typename DerivedFaces>
|
||||
IGL_INLINE void igl::copyleft::marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const Eigen::MatrixBase<DerivedIndices> & indices,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces)
|
||||
{
|
||||
MarchingCubes<DerivedValues, DerivedPoints, DerivedVertices, DerivedIndices, DerivedFaces> mc(values, points, indices, 0.0 /*isovalue*/, vertices, faces);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes< Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, const Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, const Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 8, 0, -1, 8>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, const Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>,Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, 3, 0, -1, 3> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&,const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&,const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&,Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>,Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, 8, 0, -1, 8>,Eigen::Matrix<int, -1, 3, 0, -1, 3> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&,const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&,const Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> >&,Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>,Eigen::Matrix<double, -1, 3, 0, -1, 3>,Eigen::Matrix<double, -1, 3, 0, -1, 3>,Eigen::Matrix<int, -1, 8, 0, -1, 8>,Eigen::Matrix<int, -1, 3, 0, -1, 3> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&,const Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&,const Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> >&,Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&,Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
#endif
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace igl
|
||||
{
|
||||
namespace copyleft
|
||||
{
|
||||
// marching_cubes( values, points, x_res, y_res, z_res, vertices, faces )
|
||||
// marching_cubes( values, points, x_res, y_res, z_res, isovalue, vertices, faces )
|
||||
//
|
||||
// performs marching cubes reconstruction on the grid defined by values, and
|
||||
// points, and generates vertices and faces
|
||||
// performs marching cubes reconstruction on a grid defined by values, and
|
||||
// points, and generates a mesh defined by vertices and faces
|
||||
//
|
||||
// Input:
|
||||
// values #number_of_grid_points x 1 array -- the scalar values of an
|
||||
@@ -34,24 +34,75 @@ namespace igl
|
||||
// xres resolutions of the grid in x dimension
|
||||
// yres resolutions of the grid in y dimension
|
||||
// zres resolutions of the grid in z dimension
|
||||
// isovalue the isovalue of the surface to reconstruct
|
||||
// Output:
|
||||
// vertices #V by 3 list of mesh vertex positions
|
||||
// faces #F by 3 list of mesh triangle indices
|
||||
//
|
||||
template <
|
||||
typename Derivedvalues,
|
||||
typename Derivedpoints,
|
||||
typename Derivedvertices,
|
||||
typename DerivedF>
|
||||
IGL_INLINE void marching_cubes(
|
||||
const Eigen::PlainObjectBase<Derivedvalues> &values,
|
||||
const Eigen::PlainObjectBase<Derivedpoints> &points,
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedFaces>
|
||||
IGL_INLINE void marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const unsigned x_res,
|
||||
const unsigned y_res,
|
||||
const unsigned z_res,
|
||||
Eigen::PlainObjectBase<Derivedvertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedF> &faces);
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces);
|
||||
|
||||
// Overload of the above function where the isovalue defaults to 0.0
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedFaces>
|
||||
IGL_INLINE void marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const unsigned x_res,
|
||||
const unsigned y_res,
|
||||
const unsigned z_res,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces);
|
||||
|
||||
|
||||
|
||||
// marching_cubes( values, points, indices, vertices, faces )
|
||||
//
|
||||
// Perform marching cubes reconstruction on the sparse grid cells defined by (indices, points).
|
||||
// The indices parameter is an nx8 dense array of index values into the points and values arrays.
|
||||
// Each row of indices represents a cube for which to generate vertices and faces over.
|
||||
//
|
||||
// Input:
|
||||
// values #number_of_grid_points x 1 array -- the scalar values of an
|
||||
// implicit function defined on the grid points (<0 in the inside of the
|
||||
// surface, 0 on the border, >0 outside)
|
||||
// points #number_of_grid_points x 3 array -- 3-D positions of the grid
|
||||
// points, ordered in x,y,z order:
|
||||
// indices #cubes x 8 array -- one row for each cube where each value is
|
||||
// the index of a vertex in points and a scalar in values.
|
||||
// i.e. points[indices[i, j]] = the position of the j'th vertex of the i'th cube
|
||||
// Output:
|
||||
// vertices #V by 3 list of mesh vertex positions
|
||||
// faces #F by 3 list of mesh triangle indices
|
||||
// Note: The winding direction of the cube indices will affect the output winding of the faces
|
||||
//
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedIndices, typename DerivedFaces>
|
||||
IGL_INLINE void marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const Eigen::MatrixBase<DerivedIndices> &indices,
|
||||
const double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces);
|
||||
|
||||
// Overload of the above function where the isovalue defaults to 0.0
|
||||
template <typename DerivedValues, typename DerivedPoints, typename DerivedVertices, typename DerivedIndices, typename DerivedFaces>
|
||||
IGL_INLINE void marching_cubes(
|
||||
const Eigen::MatrixBase<DerivedValues> &values,
|
||||
const Eigen::MatrixBase<DerivedPoints> &points,
|
||||
const Eigen::MatrixBase<DerivedIndices> &indices,
|
||||
Eigen::PlainObjectBase<DerivedVertices> &vertices,
|
||||
Eigen::PlainObjectBase<DerivedFaces> &faces);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -13,6 +13,94 @@
|
||||
// STL includes
|
||||
#include <cassert>
|
||||
|
||||
|
||||
IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
|
||||
const std::vector<std::vector<REAL > > & V,
|
||||
const std::vector<std::vector<int> > & F,
|
||||
const std::vector<std::vector<REAL> > & H,
|
||||
const std::vector<std::vector<REAL> > & R,
|
||||
tetgenio & in)
|
||||
{
|
||||
using namespace std;
|
||||
in.firstnumber = 0;
|
||||
in.numberofpoints = V.size();
|
||||
in.pointlist = new REAL[in.numberofpoints * 3];
|
||||
//loop over points
|
||||
for(size_t i = 0; i < (size_t)V.size(); i++)
|
||||
{
|
||||
assert(V[i].size() == 3);
|
||||
in.pointlist[i*3+0] = V[i][0];
|
||||
in.pointlist[i*3+1] = V[i][1];
|
||||
in.pointlist[i*3+2] = V[i][2];
|
||||
}
|
||||
in.numberoffacets = F.size();
|
||||
in.facetlist = new tetgenio::facet[in.numberoffacets];
|
||||
in.facetmarkerlist = new int[in.numberoffacets];
|
||||
|
||||
// loop over face
|
||||
for(size_t i = 0;i < (size_t)F.size(); i++)
|
||||
{
|
||||
in.facetmarkerlist[i] = i;
|
||||
tetgenio::facet * f = &in.facetlist[i];
|
||||
f->numberofpolygons = 1;
|
||||
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
|
||||
f->numberofholes = 0;
|
||||
f->holelist = NULL;
|
||||
tetgenio::polygon * p = &f->polygonlist[0];
|
||||
p->numberofvertices = F[i].size();
|
||||
p->vertexlist = new int[p->numberofvertices];
|
||||
// loop around face
|
||||
for(int j = 0;j < (int)F[i].size(); j++)
|
||||
{
|
||||
p->vertexlist[j] = F[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
in.numberofholes = H.size();
|
||||
in.holelist = new double[3 * in.numberofholes];
|
||||
// loop over holes
|
||||
for(size_t holeID = 0, nHoles = H.size(); holeID < nHoles; holeID++)
|
||||
{
|
||||
in.holelist[holeID * 3 + 0] = H[holeID][0];
|
||||
in.holelist[holeID * 3 + 1] = H[holeID][1];
|
||||
in.holelist[holeID * 3 + 2] = H[holeID][2];
|
||||
}
|
||||
|
||||
in.numberofregions = R.size();
|
||||
in.regionlist = new REAL[ 5 * in.numberofregions];
|
||||
// loop over regions
|
||||
for(size_t regionID = 0, nRegions = R.size(); regionID < nRegions; regionID++)
|
||||
{
|
||||
in.regionlist[regionID * 5 + 0] = R[regionID][0];
|
||||
in.regionlist[regionID * 5 + 1] = R[regionID][1];
|
||||
in.regionlist[regionID * 5 + 2] = R[regionID][2];
|
||||
in.regionlist[regionID * 5 + 3] = R[regionID][3];
|
||||
in.regionlist[regionID * 5 + 4] = R[regionID][4];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
template <typename DerivedV, typename DerivedF, typename DerivedH, typename DerivedR>
|
||||
IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F,
|
||||
const Eigen::PlainObjectBase<DerivedH>& H,
|
||||
const Eigen::PlainObjectBase<DerivedR>& R,
|
||||
tetgenio & in)
|
||||
{
|
||||
using namespace std;
|
||||
vector<vector<REAL> > vV, vH, vR;
|
||||
vector<vector<int> > vF;
|
||||
matrix_to_list(V,vV);
|
||||
matrix_to_list(F,vF);
|
||||
matrix_to_list(H, vH);
|
||||
matrix_to_list(R, vR);
|
||||
return mesh_to_tetgenio(vV,vF,vH,vR,in);
|
||||
}
|
||||
|
||||
|
||||
IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
|
||||
const std::vector<std::vector<REAL > > & V,
|
||||
const std::vector<std::vector<int> > & F,
|
||||
|
||||
@@ -43,6 +43,38 @@ namespace igl
|
||||
const Eigen::PlainObjectBase<DerivedV>& V,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F,
|
||||
tetgenio & in);
|
||||
|
||||
|
||||
// Load a vertex list and face list into a tetgenio object
|
||||
// Inputs:
|
||||
// V #V by 3 vertex position list
|
||||
// F #F list of polygon face indices into V (0-indexed)
|
||||
// H #H list of seed point inside each hole
|
||||
// R #R list of seed point inside each region
|
||||
// Outputs:
|
||||
// in tetgenio input object
|
||||
// Returns true on success, false on error
|
||||
IGL_INLINE bool mesh_to_tetgenio(
|
||||
const std::vector<std::vector<REAL> > & V,
|
||||
const std::vector<std::vector<int> > & F,
|
||||
const std::vector<std::vector<REAL > > & H,
|
||||
const std::vector<std::vector<REAL > > & R,
|
||||
tetgenio & in);
|
||||
|
||||
|
||||
// Wrapper with Eigen types
|
||||
// Templates:
|
||||
// DerivedV real-value: i.e. from MatrixXd
|
||||
// DerivedF integer-value: i.e. from MatrixXi
|
||||
// DerivedH real-value
|
||||
// DerivedR real-value
|
||||
template <typename DerivedV, typename DerivedF, typename DerivedH, typename DerivedR>
|
||||
IGL_INLINE bool mesh_to_tetgenio(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F,
|
||||
const Eigen::PlainObjectBase<DerivedH>& H,
|
||||
const Eigen::PlainObjectBase<DerivedR>& R,
|
||||
tetgenio& in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,120 @@
|
||||
// STL includes
|
||||
#include <iostream>
|
||||
|
||||
IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
|
||||
const tetgenio & out,
|
||||
std::vector<std::vector<REAL > > & V,
|
||||
std::vector<std::vector<int> > & T,
|
||||
std::vector<std::vector<int > > & F,
|
||||
std::vector<std::vector<REAL > >& R,
|
||||
std::vector<std::vector<int > >& N,
|
||||
std::vector<std::vector<int > >& PT,
|
||||
std::vector<std::vector<int > >& FT,
|
||||
size_t & nR )
|
||||
{
|
||||
using namespace std;
|
||||
// process points
|
||||
if(out.pointlist == NULL)
|
||||
{
|
||||
cerr<<"^tetgenio_to_tetmesh Error: point list is NULL\n"<<endl;
|
||||
return false;
|
||||
}
|
||||
V.resize(out.numberofpoints,vector<REAL>(3));
|
||||
// loop over points
|
||||
for(int i = 0;i < out.numberofpoints; i++)
|
||||
{
|
||||
V[i][0] = out.pointlist[i*3+0];
|
||||
V[i][1] = out.pointlist[i*3+1];
|
||||
V[i][2] = out.pointlist[i*3+2];
|
||||
}
|
||||
|
||||
// process tets
|
||||
if(out.tetrahedronlist == NULL)
|
||||
{
|
||||
cerr<<"^tetgenio_to_tetmesh Error: tet list is NULL\n"<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// When would this not be 4?
|
||||
assert(out.numberofcorners == 4);
|
||||
T.resize(out.numberoftetrahedra,vector<int>(out.numberofcorners));
|
||||
int min_index = 1e7;
|
||||
int max_index = -1e7;
|
||||
// loop over tetrahedra
|
||||
for(int i = 0; i < out.numberoftetrahedra; i++)
|
||||
{
|
||||
for(int j = 0; j<out.numberofcorners; j++)
|
||||
{
|
||||
int index = out.tetrahedronlist[i * out.numberofcorners + j];
|
||||
T[i][j] = index;
|
||||
min_index = (min_index > index ? index : min_index);
|
||||
max_index = (max_index < index ? index : max_index);
|
||||
}
|
||||
}
|
||||
|
||||
assert(min_index >= 0);
|
||||
assert(max_index >= 0);
|
||||
assert(max_index < (int)V.size());
|
||||
|
||||
cout<<out.numberoftrifaces<<endl;
|
||||
|
||||
// When would this not be 4?
|
||||
F.clear();
|
||||
// loop over tetrahedra
|
||||
for(int i = 0; i < out.numberoftrifaces; i++)
|
||||
{
|
||||
if(out.trifacemarkerlist[i]>=0)
|
||||
{
|
||||
vector<int> face(3);
|
||||
for(int j = 0; j<3; j++)
|
||||
{
|
||||
face[j] = out.trifacelist[i * 3 + j];
|
||||
}
|
||||
F.push_back(face);
|
||||
}
|
||||
}
|
||||
|
||||
R.resize(out.numberoftetrahedra, vector<REAL>(1));
|
||||
unordered_map<REAL, REAL> hashUniqueRegions;
|
||||
for(size_t i = 0; i < out.numberoftetrahedra; i++)
|
||||
{
|
||||
R[i][0] = out.tetrahedronattributelist[i];
|
||||
hashUniqueRegions[R[i][0]] = i;
|
||||
}
|
||||
// extract region marks
|
||||
nR = hashUniqueRegions.size();
|
||||
|
||||
// extract neighbor list
|
||||
N.resize(out.numberoftetrahedra, vector<int>(4));
|
||||
for (size_t i = 0; i < out.numberoftetrahedra; i++)
|
||||
{
|
||||
for (size_t j = 0; j < 4; j++)
|
||||
N[i][j] = out.neighborlist[i * 4 + j];
|
||||
}
|
||||
|
||||
// extract point 2 tetrahedron list
|
||||
PT.resize(out.numberofpoints, vector<int>(1));
|
||||
for (size_t i = 0; i < out.numberofpoints; i++)
|
||||
{
|
||||
PT[i][0] = out.point2tetlist[i];
|
||||
}
|
||||
|
||||
//extract face to tetrahedron list
|
||||
FT.resize(out.numberoftrifaces, vector<int>(2));
|
||||
int triface;
|
||||
|
||||
for (size_t i = 0; i < out.numberoftrifaces; i++)
|
||||
{
|
||||
for (size_t j = 0; j < 2; j++)
|
||||
{
|
||||
FT[i][j] = out.face2tetlist[0];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
|
||||
const tetgenio & out,
|
||||
std::vector<std::vector<REAL > > & V,
|
||||
@@ -63,8 +177,6 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
|
||||
assert(max_index >= 0);
|
||||
assert(max_index < (int)V.size());
|
||||
|
||||
cout<<out.numberoftrifaces<<endl;
|
||||
|
||||
// When would this not be 4?
|
||||
F.clear();
|
||||
// loop over tetrahedra
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#endif
|
||||
#include "tetgen.h" // Defined tetgenio, REAL
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
@@ -54,7 +55,32 @@ namespace igl
|
||||
const tetgenio & out,
|
||||
Eigen::PlainObjectBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedT>& T);
|
||||
}
|
||||
|
||||
// Extract a tetrahedral mesh from a tetgenio object
|
||||
// Inputs:
|
||||
// out tetgenio output object
|
||||
// Outputs:
|
||||
// V #V by 3 vertex position list
|
||||
// T #T by 4 list of tetrahedra indices into V
|
||||
// F #F by 3 list of marked facets
|
||||
// R #T list of region IDs for tetrahedra
|
||||
// N #T by 2 list of neighbors for each tetrahedron
|
||||
// PT #V list of incident tetrahedron for each vertex
|
||||
// FT #F by 2 list of tetrahedra sharing each face
|
||||
// nR number of regions in output mesh
|
||||
// Returns true on success, false on error
|
||||
IGL_INLINE bool tetgenio_to_tetmesh(
|
||||
const tetgenio & out,
|
||||
std::vector<std::vector<REAL > > & V,
|
||||
std::vector<std::vector<int> > & T,
|
||||
std::vector<std::vector<int> > & F,
|
||||
std::vector<std::vector<REAL> > & R,// region marks for tetrahedrons
|
||||
std::vector<std::vector<int > > &N, // neighborlist per tet
|
||||
std::vector<std::vector<int > > &PT, // Point to tet list per point
|
||||
std::vector<std::vector<int > > &FT, // face to tet list
|
||||
size_t & nR); // number of regions
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,131 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
|
||||
const std::vector<std::vector<REAL > > & V,
|
||||
const std::vector<std::vector<int> > & F,
|
||||
const std::vector<std::vector<REAL > > & H,
|
||||
const std::vector<std::vector<REAL > > & R,
|
||||
const std::string switches,
|
||||
std::vector<std::vector<REAL > > & TV,
|
||||
std::vector<std::vector<int > > & TT,
|
||||
std::vector<std::vector<int > > & TF,
|
||||
std::vector<std::vector<REAL > > &TR,
|
||||
std::vector<std::vector<int > > & TN,
|
||||
std::vector<std::vector<int > > & PT,
|
||||
std::vector<std::vector<int > > & FT,
|
||||
size_t & numRegions)
|
||||
{
|
||||
using namespace std;
|
||||
tetgenio in,out;
|
||||
bool success;
|
||||
success = mesh_to_tetgenio(V, F, H, R, in);
|
||||
if(!success)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
try
|
||||
{
|
||||
char * cswitches = new char[switches.size() + 1];
|
||||
strcpy(cswitches, switches.c_str());
|
||||
|
||||
::tetrahedralize(cswitches, &in, &out);
|
||||
delete[] cswitches;
|
||||
}catch(int e)
|
||||
{
|
||||
cerr <<"^"<<__FUNCTION__<<": TETGEN CRASHED...KABOOM!!"<<endl;
|
||||
return 1;
|
||||
}
|
||||
if(out.numberoftetrahedra == 0)
|
||||
{
|
||||
cerr<<"^"<<__FUNCTION__<<": Tetgen failed to create tets"<<endl;
|
||||
return 2;
|
||||
}
|
||||
success = tetgenio_to_tetmesh(out, TV, TT, TF, TR, TN, PT, FT, numRegions
|
||||
);
|
||||
if(!success)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedH,
|
||||
typename DerivedR,
|
||||
typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedTF,
|
||||
typename DerivedTR>
|
||||
IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F,
|
||||
const Eigen::PlainObjectBase<DerivedH>& H,
|
||||
const Eigen::PlainObjectBase<DerivedR>& R,
|
||||
const std::string switches,
|
||||
Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
Eigen::PlainObjectBase<DerivedTF>& TF,
|
||||
Eigen::PlainObjectBase<DerivedTR>& TR,
|
||||
Eigen::PlainObjectBase<DerivedTT>& TN,
|
||||
Eigen::PlainObjectBase<DerivedTT>& PT,
|
||||
Eigen::PlainObjectBase<DerivedTT>& FT,
|
||||
size_t & numRegions)
|
||||
{
|
||||
using namespace std;
|
||||
vector<vector<REAL> > vV, vH, vR, vTV, vTR;
|
||||
vector<vector<int> > vF,vTT,vTF, vTN, vPT, vFT;
|
||||
matrix_to_list(V,vV);
|
||||
matrix_to_list(F,vF);
|
||||
matrix_to_list(H, vH);
|
||||
matrix_to_list(R, vR);
|
||||
|
||||
int e = tetrahedralize(vV,vF,vH,vR,switches,vTV,vTT,vTF,vTR,vTN,vPT,vFT, numRegions);
|
||||
|
||||
if(e == 0)
|
||||
{
|
||||
bool TV_rect = list_to_matrix(vTV,TV);
|
||||
if(!TV_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool TT_rect = list_to_matrix(vTT,TT);
|
||||
if(!TT_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool TF_rect = list_to_matrix(vTF,TF);
|
||||
if(!TF_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool TR_rect = list_to_matrix(vTR, TR);
|
||||
if(!TR_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool TN_rect = list_to_matrix(vTN, TN);
|
||||
if(!TN_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool PT_rect = list_to_matrix(vPT, PT);
|
||||
if(!PT_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
bool FT_rect = list_to_matrix(vFT, FT);
|
||||
if(!FT_rect)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
|
||||
const std::vector<std::vector<REAL > > & V,
|
||||
const std::vector<std::vector<int> > & F,
|
||||
@@ -55,7 +180,7 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
//boundary_facets(TT,TF);
|
||||
boundary_facets(TT,TF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -208,7 +333,7 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
|
||||
for (int i = 0; i < out.numberofpoints; ++i) {
|
||||
TM[i] = out.pointmarkerlist[i];
|
||||
}
|
||||
//boundary_facets(TT,TF);
|
||||
boundary_facets(TT,TF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,83 @@ namespace igl
|
||||
Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
Eigen::PlainObjectBase<DerivedTF>& TF,
|
||||
Eigen::PlainObjectBase<DerivedTM>& TM);
|
||||
}
|
||||
|
||||
|
||||
// Mesh the interior of a surface mesh (V,F) using tetgen
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 vertex position list
|
||||
// F #F list of polygon face indices into V (0-indexed)
|
||||
// H #H by 3 list of seed points inside holes
|
||||
// R #R by 5 list of region attributes
|
||||
|
||||
// switches string of tetgen options (See tetgen documentation) e.g.
|
||||
// "pq1.414a0.01" tries to mesh the interior of a given surface with
|
||||
// quality and area constraints
|
||||
// "" will mesh the convex hull constrained to pass through V (ignores F)
|
||||
// Outputs:
|
||||
// TV #V by 3 vertex position list
|
||||
// TT #T by 4 list of tet face indices
|
||||
// TF #F by 3 list of triangle face indices
|
||||
// TR #T list of region ID for each tetrahedron
|
||||
// TN #T by 4 list of indices neighbors for each tetrahedron
|
||||
// PT #V list of incident tetrahedron for a vertex
|
||||
// FT #F by 2 list of tetrahedrons sharing a triface
|
||||
// numRegions Number of regions in output mesh
|
||||
|
||||
// Returns status:
|
||||
// 0 success
|
||||
// 1 tetgen threw exception
|
||||
// 2 tetgen did not crash but could not create any tets (probably there are
|
||||
// holes, duplicate faces etc.)
|
||||
// -1 other error
|
||||
IGL_INLINE int tetrahedralize(
|
||||
const std::vector<std::vector<REAL> > &V,
|
||||
const std::vector<std::vector<int> > &F,
|
||||
const std::vector<std::vector<REAL> > &H,
|
||||
const std::vector<std::vector<REAL> > &R,
|
||||
|
||||
const std::string switches,
|
||||
|
||||
std::vector<std::vector<REAL > > & TV,
|
||||
std::vector<std::vector<int > > & TT,
|
||||
std::vector<std::vector<int > > & TF,
|
||||
std::vector<std::vector<REAL > > &TR,
|
||||
std::vector<std::vector<int > > &TN,
|
||||
std::vector<std::vector<int > > &PT,
|
||||
std::vector<std::vector<int > > &FT,
|
||||
size_t & numRegions);
|
||||
|
||||
|
||||
// Wrapper with Eigen types
|
||||
// Templates:
|
||||
// DerivedV real-value: i.e. from MatrixXd
|
||||
// DerivedF integer-value: i.e. from MatrixXi
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedH,
|
||||
typename DerivedR,
|
||||
typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedTF,
|
||||
typename DerivedTR>
|
||||
IGL_INLINE int tetrahedralize(
|
||||
const Eigen::PlainObjectBase<DerivedV>& V,
|
||||
const Eigen::PlainObjectBase<DerivedF>& F,
|
||||
const Eigen::PlainObjectBase<DerivedH>& H,
|
||||
const Eigen::PlainObjectBase<DerivedR>& R,
|
||||
const std::string switches,
|
||||
Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
Eigen::PlainObjectBase<DerivedTF>& TF,
|
||||
Eigen::PlainObjectBase<DerivedTR>& TR,
|
||||
Eigen::PlainObjectBase<DerivedTT>& TN,
|
||||
Eigen::PlainObjectBase<DerivedTT>& PT,
|
||||
Eigen::PlainObjectBase<DerivedTT>& FT,
|
||||
size_t & numRegions);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace igl
|
||||
// Scalar scalar type for eigen sparse matrix (e.g. double)
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions
|
||||
// F #F by simplex_size list of mesh faces (must be triangles)
|
||||
// F #F by simplex_size list of mesh elements (triangles or tetrahedra)
|
||||
// Outputs:
|
||||
// L #V by #V cotangent matrix, each row i corresponding to V(i,:)
|
||||
//
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
#include "cut_to_disk.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
|
||||
namespace igl {
|
||||
template <typename DerivedF, typename Index>
|
||||
void cut_to_disk(
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
std::vector<std::vector<Index> > &cuts)
|
||||
{
|
||||
cuts.clear();
|
||||
|
||||
Index nfaces = F.rows();
|
||||
|
||||
if (nfaces == 0)
|
||||
return;
|
||||
|
||||
std::map<std::pair<Index, Index>, std::vector<Index> > edges;
|
||||
// build edges
|
||||
|
||||
for (Index i = 0; i < nfaces; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
Index v0 = F(i, j);
|
||||
Index v1 = F(i, (j + 1) % 3);
|
||||
std::pair<Index, Index> e;
|
||||
e.first = std::min(v0, v1);
|
||||
e.second = std::max(v0, v1);
|
||||
edges[e].push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
int nedges = edges.size();
|
||||
Eigen::Matrix<Index, -1, -1> edgeVerts(nedges,2);
|
||||
Eigen::Matrix<Index, -1, -1> edgeFaces(nedges,2);
|
||||
Eigen::Matrix<Index, -1, -1> faceEdges(nfaces, 3);
|
||||
std::set<Index> boundaryEdges;
|
||||
std::map<std::pair<Index, Index>, Index> edgeidx;
|
||||
Index idx = 0;
|
||||
for (auto it : edges)
|
||||
{
|
||||
edgeidx[it.first] = idx;
|
||||
edgeVerts(idx, 0) = it.first.first;
|
||||
edgeVerts(idx, 1) = it.first.second;
|
||||
edgeFaces(idx, 0) = it.second[0];
|
||||
if (it.second.size() > 1)
|
||||
{
|
||||
edgeFaces(idx, 1) = it.second[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeFaces(idx, 1) = -1;
|
||||
boundaryEdges.insert(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
for (Index i = 0; i < nfaces; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
Index v0 = F(i, j);
|
||||
Index v1 = F(i, (j + 1) % 3);
|
||||
std::pair<Index, Index> e;
|
||||
e.first = std::min(v0, v1);
|
||||
e.second = std::max(v0, v1);
|
||||
faceEdges(i, j) = edgeidx[e];
|
||||
}
|
||||
}
|
||||
|
||||
bool *deleted = new bool[nfaces];
|
||||
for (Index i = 0; i < nfaces; i++)
|
||||
deleted[i] = false;
|
||||
|
||||
std::set<Index> deletededges;
|
||||
|
||||
// loop over faces
|
||||
for (Index face = 0; face < nfaces; face++)
|
||||
{
|
||||
// stop at first undeleted face
|
||||
if (deleted[face])
|
||||
continue;
|
||||
deleted[face] = true;
|
||||
std::deque<Index> processEdges;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Index e = faceEdges(face, i);
|
||||
if (boundaryEdges.count(e))
|
||||
continue;
|
||||
int ndeleted = 0;
|
||||
if (deleted[edgeFaces(e, 0)])
|
||||
ndeleted++;
|
||||
if (deleted[edgeFaces(e, 1)])
|
||||
ndeleted++;
|
||||
if (ndeleted == 1)
|
||||
processEdges.push_back(e);
|
||||
}
|
||||
// delete all faces adjacent to edges with exactly one adjacent face
|
||||
while (!processEdges.empty())
|
||||
{
|
||||
Index nexte = processEdges.front();
|
||||
processEdges.pop_front();
|
||||
Index todelete = nfaces;
|
||||
if (!deleted[edgeFaces(nexte, 0)])
|
||||
todelete = edgeFaces(nexte, 0);
|
||||
if (!deleted[edgeFaces(nexte, 1)])
|
||||
todelete = edgeFaces(nexte, 1);
|
||||
if (todelete != nfaces)
|
||||
{
|
||||
deletededges.insert(nexte);
|
||||
deleted[todelete] = true;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Index e = faceEdges(todelete, i);
|
||||
if (boundaryEdges.count(e))
|
||||
continue;
|
||||
int ndeleted = 0;
|
||||
if (deleted[edgeFaces(e, 0)])
|
||||
ndeleted++;
|
||||
if (deleted[edgeFaces(e, 1)])
|
||||
ndeleted++;
|
||||
if (ndeleted == 1)
|
||||
processEdges.push_back(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] deleted;
|
||||
|
||||
// accumulated non-deleted edges
|
||||
std::vector<Index> leftedges;
|
||||
for (Index i = 0; i < nedges; i++)
|
||||
{
|
||||
if (!deletededges.count(i))
|
||||
leftedges.push_back(i);
|
||||
}
|
||||
|
||||
deletededges.clear();
|
||||
// prune spines
|
||||
std::map<Index, std::vector<Index> > spinevertedges;
|
||||
for (Index i : leftedges)
|
||||
{
|
||||
spinevertedges[edgeVerts(i, 0)].push_back(i);
|
||||
spinevertedges[edgeVerts(i, 1)].push_back(i);
|
||||
}
|
||||
|
||||
std::deque<Index> vertsProcess;
|
||||
std::map<Index, int> spinevertnbs;
|
||||
for (auto it : spinevertedges)
|
||||
{
|
||||
spinevertnbs[it.first] = it.second.size();
|
||||
if (it.second.size() == 1)
|
||||
vertsProcess.push_back(it.first);
|
||||
}
|
||||
while (!vertsProcess.empty())
|
||||
{
|
||||
Index vert = vertsProcess.front();
|
||||
vertsProcess.pop_front();
|
||||
for (Index e : spinevertedges[vert])
|
||||
{
|
||||
if (!deletededges.count(e))
|
||||
{
|
||||
deletededges.insert(e);
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
spinevertnbs[edgeVerts(e, j)]--;
|
||||
if (spinevertnbs[edgeVerts(e, j)] == 1)
|
||||
{
|
||||
vertsProcess.push_back(edgeVerts(e, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<Index> loopedges;
|
||||
for (Index i : leftedges)
|
||||
if (!deletededges.count(i))
|
||||
loopedges.push_back(i);
|
||||
|
||||
Index nloopedges = loopedges.size();
|
||||
if (nloopedges == 0)
|
||||
return;
|
||||
|
||||
std::map<Index, std::vector<Index> > loopvertedges;
|
||||
for (Index e : loopedges)
|
||||
{
|
||||
loopvertedges[edgeVerts(e, 0)].push_back(e);
|
||||
loopvertedges[edgeVerts(e, 1)].push_back(e);
|
||||
}
|
||||
|
||||
std::set<Index> usededges;
|
||||
for (Index e : loopedges)
|
||||
{
|
||||
// make a cycle or chain starting from this edge
|
||||
while (!usededges.count(e))
|
||||
{
|
||||
std::vector<Index> cycleverts;
|
||||
std::vector<Index> cycleedges;
|
||||
cycleverts.push_back(edgeVerts(e, 0));
|
||||
cycleverts.push_back(edgeVerts(e, 1));
|
||||
cycleedges.push_back(e);
|
||||
|
||||
std::map<Index, Index> cycleidx;
|
||||
cycleidx[cycleverts[0]] = 0;
|
||||
cycleidx[cycleverts[1]] = 1;
|
||||
|
||||
Index curvert = edgeVerts(e, 1);
|
||||
Index cure = e;
|
||||
bool foundcycle = false;
|
||||
while (curvert != -1 && !foundcycle)
|
||||
{
|
||||
Index nextvert = -1;
|
||||
Index nexte = -1;
|
||||
for (Index cande : loopvertedges[curvert])
|
||||
{
|
||||
if (!usededges.count(cande) && cande != cure)
|
||||
{
|
||||
int vidx = 0;
|
||||
if (curvert == edgeVerts(cande, vidx))
|
||||
vidx = 1;
|
||||
nextvert = edgeVerts(cande, vidx);
|
||||
nexte = cande;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nextvert != -1)
|
||||
{
|
||||
auto it = cycleidx.find(nextvert);
|
||||
if (it != cycleidx.end())
|
||||
{
|
||||
// we've hit outselves
|
||||
std::vector<Index> cut;
|
||||
for (Index i = it->second; i < cycleverts.size(); i++)
|
||||
{
|
||||
cut.push_back(cycleverts[i]);
|
||||
}
|
||||
cut.push_back(nextvert);
|
||||
cuts.push_back(cut);
|
||||
for (Index i = it->second; i < cycleedges.size(); i++)
|
||||
{
|
||||
usededges.insert(cycleedges[i]);
|
||||
}
|
||||
usededges.insert(nexte);
|
||||
foundcycle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cycleidx[nextvert] = cycleverts.size();
|
||||
cycleverts.push_back(nextvert);
|
||||
cycleedges.push_back(nexte);
|
||||
}
|
||||
}
|
||||
curvert = nextvert;
|
||||
cure = nexte;
|
||||
}
|
||||
if (!foundcycle)
|
||||
{
|
||||
// we've hit a dead end. reverse and try the other direction
|
||||
std::reverse(cycleverts.begin(), cycleverts.end());
|
||||
std::reverse(cycleedges.begin(), cycleedges.end());
|
||||
curvert = cycleverts.back();
|
||||
cure = cycleedges.back();
|
||||
while (curvert != -1 && !foundcycle)
|
||||
{
|
||||
Index nextvert = -1;
|
||||
Index nexte = -1;
|
||||
for (Index cande : loopvertedges[curvert])
|
||||
{
|
||||
if (!usededges.count(cande) && cande != cure)
|
||||
{
|
||||
int vidx = 0;
|
||||
if (curvert == edgeVerts(cande, vidx))
|
||||
vidx = 1;
|
||||
nextvert = edgeVerts(cande, vidx);
|
||||
nexte = cande;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nextvert != -1)
|
||||
{
|
||||
auto it = cycleidx.find(nextvert);
|
||||
if (it != cycleidx.end())
|
||||
{
|
||||
// we've hit outselves
|
||||
std::vector<int> cut;
|
||||
for (Index i = it->second; i < cycleverts.size(); i++)
|
||||
{
|
||||
cut.push_back(cycleverts[i]);
|
||||
}
|
||||
cut.push_back(nextvert);
|
||||
cuts.push_back(cut);
|
||||
for (Index i = it->second; i < cycleedges.size(); i++)
|
||||
{
|
||||
usededges.insert(cycleedges[i]);
|
||||
}
|
||||
usededges.insert(nexte);
|
||||
foundcycle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cycleidx[nextvert] = cycleverts.size();
|
||||
cycleverts.push_back(nextvert);
|
||||
cycleedges.push_back(nexte);
|
||||
}
|
||||
}
|
||||
curvert = nextvert;
|
||||
cure = nexte;
|
||||
}
|
||||
if (!foundcycle)
|
||||
{
|
||||
// we've found a chain
|
||||
std::vector<Index> cut;
|
||||
for (Index i = 0; i < cycleverts.size(); i++)
|
||||
{
|
||||
cut.push_back(cycleverts[i]);
|
||||
}
|
||||
cuts.push_back(cut);
|
||||
for (Index i = 0; i < cycleedges.size(); i++)
|
||||
{
|
||||
usededges.insert(cycleedges[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::cut_to_disk<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef IGL_CUT_TO_DISK_H
|
||||
#define IGL_CUT_TO_DISK_H
|
||||
#include "igl_inline.h"
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// Given a triangle mesh, computes a set of edge cuts sufficient to carve the
|
||||
// mesh into a topological disk, without disconnecting any connected components.
|
||||
// Nothing else about the cuts (including number, total length, or smoothness)
|
||||
// is guaranteed to be optimal.
|
||||
//
|
||||
// Simply-connected components without boundary (topological spheres) are left
|
||||
// untouched (delete any edge if you really want a disk).
|
||||
// All other connected components are cut into disks. Meshes with boundary are
|
||||
// supported; boundary edges will be included as cuts.
|
||||
//
|
||||
// The cut mesh itself can be materialized using cut_mesh().
|
||||
//
|
||||
// Implements the triangle-deletion approach described by Gu et al's
|
||||
// "Geometry Images."
|
||||
//
|
||||
// Template Parameters:
|
||||
// Index Integrable type large enough to represent the total number of faces
|
||||
// and edges in the surface represented by F, and all entries of F.
|
||||
//
|
||||
// Inputs:
|
||||
// F #F by 3 list of the faces (must be triangles)
|
||||
//
|
||||
// Outputs:
|
||||
// cuts List of cuts. Each cut is a sequence of vertex indices (where
|
||||
// pairs of consecutive vertices share a face), is simple, and is either
|
||||
// a closed loop (in which the first and last indices are identical) or
|
||||
// an open curve. Cuts are edge-disjoint.
|
||||
//
|
||||
|
||||
template <
|
||||
typename DerivedF,
|
||||
typename Index>
|
||||
IGL_INLINE void cut_to_disk(
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
std::vector<std::vector<Index> > &cuts);
|
||||
};
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
#include "cut_to_disk.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+27
-12
@@ -5,14 +5,16 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include <igl/dijkstra.h>
|
||||
#include "dijkstra.h"
|
||||
|
||||
template <typename IndexType, typename DerivedD, typename DerivedP>
|
||||
IGL_INLINE int igl::dijkstra_compute_paths(const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous)
|
||||
IGL_INLINE int igl::dijkstra(
|
||||
const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
const std::vector<double>& weights,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous)
|
||||
{
|
||||
int numV = VV.size();
|
||||
min_distance.setConstant(numV, 1, std::numeric_limits<typename DerivedD::Scalar>::infinity());
|
||||
@@ -37,7 +39,7 @@ IGL_INLINE int igl::dijkstra_compute_paths(const IndexType &source,
|
||||
neighbor_iter++)
|
||||
{
|
||||
IndexType v = *neighbor_iter;
|
||||
typename DerivedD::Scalar distance_through_u = dist + 1.;
|
||||
typename DerivedD::Scalar distance_through_u = dist + weights[u];
|
||||
if (distance_through_u < min_distance[v]) {
|
||||
vertex_queue.erase(std::make_pair(min_distance[v], v));
|
||||
|
||||
@@ -53,10 +55,23 @@ IGL_INLINE int igl::dijkstra_compute_paths(const IndexType &source,
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename IndexType, typename DerivedD, typename DerivedP>
|
||||
IGL_INLINE int igl::dijkstra(
|
||||
const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous)
|
||||
{
|
||||
std::vector<double> weights(VV.size(), 1.0);
|
||||
return dijkstra(source, targets, VV, weights, min_distance, previous);
|
||||
}
|
||||
|
||||
template <typename IndexType, typename DerivedP>
|
||||
IGL_INLINE void igl::dijkstra_get_shortest_path_to(const IndexType &vertex,
|
||||
const Eigen::PlainObjectBase<DerivedP> &previous,
|
||||
std::vector<IndexType> &path)
|
||||
IGL_INLINE void igl::dijkstra(
|
||||
const IndexType &vertex,
|
||||
const Eigen::MatrixBase<DerivedP> &previous,
|
||||
std::vector<IndexType> &path)
|
||||
{
|
||||
IndexType source = vertex;
|
||||
path.clear();
|
||||
@@ -66,6 +81,6 @@ IGL_INLINE void igl::dijkstra_get_shortest_path_to(const IndexType &vertex,
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template int igl::dijkstra_compute_paths<int, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, std::set<int, std::less<int>, std::allocator<int> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::dijkstra_get_shortest_path_to<int, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<int, std::allocator<int> >&);
|
||||
template int igl::dijkstra<int, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, std::set<int, std::less<int>, std::allocator<int> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::dijkstra<int, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<int, std::allocator<int> >&);
|
||||
#endif
|
||||
|
||||
+35
-10
@@ -16,7 +16,30 @@
|
||||
|
||||
namespace igl {
|
||||
|
||||
// Dijstra's algorithm for shortest paths, with multiple targets.
|
||||
// Dijkstra's algorithm for vertex-weighted shortest paths, with multiple targets.
|
||||
// Adapted from http://rosettacode.org/wiki/Dijkstra%27s_algorithm .
|
||||
//
|
||||
// Inputs:
|
||||
// source index of source vertex
|
||||
// targets target vector set
|
||||
// VV #V list of lists of incident vertices (adjacency list), e.g.
|
||||
// as returned by igl::adjacency_list
|
||||
// weights #V list of scalar vertex weights
|
||||
//
|
||||
// Output:
|
||||
// min_distance #V by 1 list of the minimum distances from source to all vertices
|
||||
// previous #V by 1 list of the previous visited vertices (for each vertex) - used for backtracking
|
||||
//
|
||||
template <typename IndexType, typename DerivedD, typename DerivedP>
|
||||
IGL_INLINE int dijkstra(
|
||||
const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
const std::vector<double>& weights,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous);
|
||||
|
||||
// Dijkstra's algorithm for shortest paths, with multiple targets.
|
||||
// Adapted from http://rosettacode.org/wiki/Dijkstra%27s_algorithm .
|
||||
//
|
||||
// Inputs:
|
||||
@@ -30,13 +53,14 @@ namespace igl {
|
||||
// previous #V by 1 list of the previous visited vertices (for each vertex) - used for backtracking
|
||||
//
|
||||
template <typename IndexType, typename DerivedD, typename DerivedP>
|
||||
IGL_INLINE int dijkstra_compute_paths(const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous);
|
||||
IGL_INLINE int dijkstra(
|
||||
const IndexType &source,
|
||||
const std::set<IndexType> &targets,
|
||||
const std::vector<std::vector<IndexType> >& VV,
|
||||
Eigen::PlainObjectBase<DerivedD> &min_distance,
|
||||
Eigen::PlainObjectBase<DerivedP> &previous);
|
||||
|
||||
// Backtracking after Dijstra's algorithm, to find shortest path.
|
||||
// Backtracking after Dijkstra's algorithm, to find shortest path.
|
||||
//
|
||||
// Inputs:
|
||||
// vertex vertex to which we want the shortest path (from same source as above)
|
||||
@@ -46,9 +70,10 @@ namespace igl {
|
||||
// path #P by 1 list of vertex indices in the shortest path from source to vertex
|
||||
//
|
||||
template <typename IndexType, typename DerivedP>
|
||||
IGL_INLINE void dijkstra_get_shortest_path_to(const IndexType &vertex,
|
||||
const Eigen::PlainObjectBase<DerivedP> &previous,
|
||||
std::vector<IndexType> &path);
|
||||
IGL_INLINE void dijkstra(
|
||||
const IndexType &vertex,
|
||||
const Eigen::MatrixBase<DerivedP> &previous,
|
||||
std::vector<IndexType> &path);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+9
-15
@@ -1,5 +1,6 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Alec Jacobson <alecjacobson@gmail.com>
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
@@ -16,31 +17,24 @@ IGL_INLINE std::string igl::dirname(const std::string & path)
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
#if defined (WIN32)
|
||||
char del('\\');
|
||||
#else
|
||||
char del('/');
|
||||
#endif
|
||||
// http://stackoverflow.com/questions/5077693/dirnamephp-similar-function-in-c
|
||||
std::string::const_reverse_iterator last_slash =
|
||||
std::find(
|
||||
path.rbegin(),
|
||||
path.rend(),del);
|
||||
if( last_slash == path.rend() )
|
||||
// https://stackoverflow.com/a/3071694/148668
|
||||
size_t found = path.find_last_of("/\\");
|
||||
if(found == std::string::npos)
|
||||
{
|
||||
// No slashes found
|
||||
return std::string(".");
|
||||
}else if(1 == (last_slash.base() - path.begin()))
|
||||
}else if(found == 0)
|
||||
{
|
||||
// Slash is first char
|
||||
return std::string(&del);
|
||||
}else if(path.end() == last_slash.base() )
|
||||
return std::string(path.begin(),path.begin()+1);
|
||||
}else if(found == path.length()-1)
|
||||
{
|
||||
// Slash is last char
|
||||
std::string redo = std::string(path.begin(),path.end()-1);
|
||||
return igl::dirname(redo);
|
||||
}
|
||||
return std::string(path.begin(),last_slash.base()-1);
|
||||
// Return everything up to but not including last slash
|
||||
return std::string(path.begin(),path.begin()+found);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Alec Jacobson <alecjacobson@gmail.com>
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
@@ -19,6 +20,10 @@ namespace igl
|
||||
// Returns string containing dirname (see php's dirname)
|
||||
//
|
||||
// See also: basename, pathinfo
|
||||
//
|
||||
// **Note:** This function will have undefined behavior if **file names** in
|
||||
// the path contain \ and / characters. This function interprets \ and / as
|
||||
// file path separators.
|
||||
IGL_INLINE std::string dirname(const std::string & path);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "edges.h"
|
||||
#include "adjacency_matrix.h"
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
template <typename DerivedF, typename DerivedE>
|
||||
IGL_INLINE void igl::edges(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedE> & E)
|
||||
{
|
||||
// build adjacency matrix
|
||||
@@ -44,4 +44,5 @@ IGL_INLINE void igl::edges(
|
||||
// Explicit template instantiation
|
||||
template void igl::edges<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
|
||||
template void igl::edges<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::edges<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
a0c5a93d2bc144890fbfa8d5e413d4dddc4a2827
|
||||
@@ -14,6 +14,8 @@ namespace igl
|
||||
{
|
||||
// Compute connected components of facets based on edge-edge adjacency.
|
||||
//
|
||||
// For connected components on vertices see igl::vertex_components
|
||||
//
|
||||
// Inputs:
|
||||
// F #F by 3 list of triangle indices
|
||||
// Outputs:
|
||||
@@ -22,6 +24,11 @@ namespace igl
|
||||
IGL_INLINE void facet_components(
|
||||
const Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedC> & C);
|
||||
|
||||
// Compute connected components of facets based on edge-edge adjacency.
|
||||
//
|
||||
// For connected components on vertices see igl::vertex_components
|
||||
//
|
||||
// Inputs:
|
||||
// TT #TT by 3 list of list of adjacency triangles (see
|
||||
// triangle_triangle_adjacency.h)
|
||||
|
||||
@@ -102,4 +102,7 @@ namespace igl {
|
||||
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template void igl::knn<Eigen::Matrix<double, -1, -1, 0, -1, -1>, int, int, Eigen::Matrix<int, -1, 8, 0, -1, 8>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "lim.h"
|
||||
#include <LIMSolverInterface.h>
|
||||
|
||||
|
||||
IGL_INLINE igl::lim::State igl::lim::lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima)
|
||||
{
|
||||
return (State)ComputeLIM(
|
||||
vertices,
|
||||
initialVertices,
|
||||
elements,
|
||||
constraintMatrix,
|
||||
constraintTargets,
|
||||
(EnergyType)energyType,
|
||||
tolerance,
|
||||
maxIteration,
|
||||
findLocalMinima
|
||||
);
|
||||
}
|
||||
|
||||
IGL_INLINE igl::lim::State igl::lim::lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima,
|
||||
bool enableOuput,
|
||||
bool enableBarriers,
|
||||
bool enableAlphaUpdate,
|
||||
double beta,
|
||||
double eps)
|
||||
{
|
||||
return (State)ComputeLIM(
|
||||
vertices,
|
||||
initialVertices,
|
||||
elements,
|
||||
constraintMatrix,
|
||||
constraintTargets,
|
||||
(EnergyType)energyType,
|
||||
tolerance,
|
||||
maxIteration,
|
||||
findLocalMinima,
|
||||
enableOuput,
|
||||
enableBarriers,
|
||||
enableAlphaUpdate,
|
||||
beta,
|
||||
eps
|
||||
);
|
||||
}
|
||||
|
||||
IGL_INLINE igl::lim::State igl::lim::lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const std::vector<int>& borderVertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& gradients,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima)
|
||||
{
|
||||
return (State)ComputeLIM(
|
||||
vertices,
|
||||
initialVertices,
|
||||
elements,
|
||||
borderVertices,
|
||||
gradients,
|
||||
constraintMatrix,
|
||||
constraintTargets,
|
||||
(EnergyType)energyType,
|
||||
tolerance,
|
||||
maxIteration,
|
||||
findLocalMinima
|
||||
);
|
||||
}
|
||||
|
||||
IGL_INLINE igl::lim::State igl::lim::lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const std::vector<int>& borderVertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& gradients,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima,
|
||||
bool enableOuput,
|
||||
bool enableBarriers,
|
||||
bool enableAlphaUpdate,
|
||||
double beta,
|
||||
double eps)
|
||||
{
|
||||
return (State)ComputeLIM(
|
||||
vertices,
|
||||
initialVertices,
|
||||
elements,
|
||||
borderVertices,
|
||||
gradients,
|
||||
constraintMatrix,
|
||||
constraintTargets,
|
||||
(EnergyType)energyType,
|
||||
tolerance,
|
||||
maxIteration,
|
||||
findLocalMinima,
|
||||
enableOuput,
|
||||
enableBarriers,
|
||||
enableAlphaUpdate,
|
||||
beta,
|
||||
eps);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
@@ -1,133 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_LIM_LIM_H
|
||||
#define IGL_LIM_LIM_H
|
||||
#include <igl/igl_inline.h>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Sparse>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace lim
|
||||
{
|
||||
// Computes a locally injective mapping of a triangle or tet-mesh based on
|
||||
// a deformation energy subject to some provided linear positional
|
||||
// constraints Cv-d.
|
||||
//
|
||||
// Inputs:
|
||||
// vertices vx3 matrix containing vertex position of the mesh
|
||||
// initialVertices vx3 matrix containing vertex position of initial
|
||||
// rest pose mesh
|
||||
// elements exd matrix containing vertex indices of all elements
|
||||
// borderVertices (only needed for 2D LSCM) vector containing indices
|
||||
// of border vertices
|
||||
// gradients (only needed for 2D Poisson) vector containing
|
||||
// partial derivatives of target element gradients
|
||||
// (structure is: [xx_0, xy_0, xx_1, xy_1, ..., xx_v,
|
||||
// xy_v, yx_0, yy_0, yx_1, yy_1, ..., yx_v, yy_v]')
|
||||
// constraintMatrix C: (c)x(v*(d-1)) sparse linear positional constraint
|
||||
// matrix. X an Y-coordinates are alternatingly stacked
|
||||
// per row (structure for triangles: [x_1, y_1, x_2,
|
||||
// y_2, ..., x_v,y_v])
|
||||
// constraintTargets d: c vector target positions
|
||||
// energyType type of used energy:
|
||||
// Dirichlet, Laplacian, Green, ARAP, LSCM, Poisson (only 2D), UniformLaplacian, Identity
|
||||
// tolerance max squared positional constraints error
|
||||
// maxIteration max number of iterations
|
||||
// findLocalMinima iterating until a local minima is found. If not
|
||||
// enabled only tolerance must be fulfilled.
|
||||
// enableOutput (optional) enables the output (#iteration / hessian correction / step size / positional constraints / barrier constraints / deformation energy) (default : true)
|
||||
// enableBarriers (optional) enables the non-flip constraints (default = true)
|
||||
// enableAlphaUpdate (optional) enables dynamic alpha weight adjustment (default = true)
|
||||
// beta (optional) steepness factor of barrier slopes (default: ARAP/LSCM = 0.01, Green = 1)
|
||||
// eps (optional) smallest valid triangle area (default: 1e-5 * smallest triangle)
|
||||
//
|
||||
// where:
|
||||
// v : # vertices
|
||||
// c : # linear constraints
|
||||
// e : # elements of mesh
|
||||
// d : # vertices per element (triangle = 3, tet = 4)
|
||||
//--------------------------------------------------------------------------
|
||||
// Output:
|
||||
// vertices vx3 matrix containing resulting vertex position of the
|
||||
// mesh
|
||||
//--------------------------------------------------------------------------
|
||||
// Return values:
|
||||
// Succeeded : Successful optimization with fulfilled tolerance
|
||||
// LocalMinima : Convergenged to a local minima / tolerance not fulfilled
|
||||
// IterationLimit : Max iteration reached before tolerance was fulfilled
|
||||
// Infeasible : not feasible -> has inverted elements (decrease eps?)
|
||||
|
||||
enum Energy { Dirichlet = 0, Laplacian=1, Green=2, ARAP=3, LSCM=4, Poisson=5, UniformLaplacian=6, Identity=7 };
|
||||
enum State { Uninitialized = -4, Infeasible = -3, IterationLimit = -2, LocalMinima = -1, Running = 0, Succeeded = 1 };
|
||||
|
||||
State lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima);
|
||||
|
||||
State lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima,
|
||||
bool enableOuput,
|
||||
bool enableBarriers,
|
||||
bool enableAlphaUpdate,
|
||||
double beta,
|
||||
double eps);
|
||||
|
||||
State lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const std::vector<int>& borderVertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& gradients,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima);
|
||||
|
||||
State lim(
|
||||
Eigen::Matrix<double,Eigen::Dynamic,3>& vertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,3>& initialVertices,
|
||||
const Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>& elements,
|
||||
const std::vector<int>& borderVertices,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& gradients,
|
||||
const Eigen::SparseMatrix<double>& constraintMatrix,
|
||||
const Eigen::Matrix<double,Eigen::Dynamic,1>& constraintTargets,
|
||||
Energy energyType,
|
||||
double tolerance,
|
||||
int maxIteration,
|
||||
bool findLocalMinima,
|
||||
bool enableOuput,
|
||||
bool enableBarriers,
|
||||
bool enableAlphaUpdate,
|
||||
double beta,
|
||||
double eps);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "lim.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Zhongshi Jiang <jiangzs@nyu.edu>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "mapping_energy_with_jacobians.h"
|
||||
#include "polar_svd.h"
|
||||
|
||||
IGL_INLINE double igl::mapping_energy_with_jacobians(
|
||||
const Eigen::MatrixXd &Ji,
|
||||
const Eigen::VectorXd &areas,
|
||||
igl::MappingEnergyType slim_energy,
|
||||
double exp_factor){
|
||||
|
||||
double energy = 0;
|
||||
if (Ji.cols() == 4)
|
||||
{
|
||||
Eigen::Matrix<double, 2, 2> ji;
|
||||
for (int i = 0; i < Ji.rows(); i++)
|
||||
{
|
||||
ji(0, 0) = Ji(i, 0);
|
||||
ji(0, 1) = Ji(i, 1);
|
||||
ji(1, 0) = Ji(i, 2);
|
||||
ji(1, 1) = Ji(i, 3);
|
||||
|
||||
typedef Eigen::Matrix<double, 2, 2> Mat2;
|
||||
typedef Eigen::Matrix<double, 2, 1> Vec2;
|
||||
Mat2 ri, ti, ui, vi;
|
||||
Vec2 sing;
|
||||
igl::polar_svd(ji, ri, ti, ui, sing, vi);
|
||||
double s1 = sing(0);
|
||||
double s2 = sing(1);
|
||||
|
||||
switch (slim_energy)
|
||||
{
|
||||
case igl::MappingEnergyType::ARAP:
|
||||
{
|
||||
energy += areas(i) * (pow(s1 - 1, 2) + pow(s2 - 1, 2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::SYMMETRIC_DIRICHLET:
|
||||
{
|
||||
energy += areas(i) * (pow(s1, 2) + pow(s1, -2) + pow(s2, 2) + pow(s2, -2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::EXP_SYMMETRIC_DIRICHLET:
|
||||
{
|
||||
energy += areas(i) * exp(exp_factor * (pow(s1, 2) + pow(s1, -2) + pow(s2, 2) + pow(s2, -2)));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::LOG_ARAP:
|
||||
{
|
||||
energy += areas(i) * (pow(log(s1), 2) + pow(log(s2), 2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::CONFORMAL:
|
||||
{
|
||||
energy += areas(i) * ((pow(s1, 2) + pow(s2, 2)) / (2 * s1 * s2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::EXP_CONFORMAL:
|
||||
{
|
||||
energy += areas(i) * exp(exp_factor * ((pow(s1, 2) + pow(s2, 2)) / (2 * s1 * s2)));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Eigen::Matrix<double, 3, 3> ji;
|
||||
for (int i = 0; i < Ji.rows(); i++)
|
||||
{
|
||||
ji(0, 0) = Ji(i, 0);
|
||||
ji(0, 1) = Ji(i, 1);
|
||||
ji(0, 2) = Ji(i, 2);
|
||||
ji(1, 0) = Ji(i, 3);
|
||||
ji(1, 1) = Ji(i, 4);
|
||||
ji(1, 2) = Ji(i, 5);
|
||||
ji(2, 0) = Ji(i, 6);
|
||||
ji(2, 1) = Ji(i, 7);
|
||||
ji(2, 2) = Ji(i, 8);
|
||||
|
||||
typedef Eigen::Matrix<double, 3, 3> Mat3;
|
||||
typedef Eigen::Matrix<double, 3, 1> Vec3;
|
||||
Mat3 ri, ti, ui, vi;
|
||||
Vec3 sing;
|
||||
igl::polar_svd(ji, ri, ti, ui, sing, vi);
|
||||
double s1 = sing(0);
|
||||
double s2 = sing(1);
|
||||
double s3 = sing(2);
|
||||
|
||||
switch (slim_energy)
|
||||
{
|
||||
case igl::MappingEnergyType::ARAP:
|
||||
{
|
||||
energy += areas(i) * (pow(s1 - 1, 2) + pow(s2 - 1, 2) + pow(s3 - 1, 2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::SYMMETRIC_DIRICHLET:
|
||||
{
|
||||
energy += areas(i) * (pow(s1, 2) + pow(s1, -2) + pow(s2, 2) + pow(s2, -2) + pow(s3, 2) + pow(s3, -2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::EXP_SYMMETRIC_DIRICHLET:
|
||||
{
|
||||
energy += areas(i) * exp(exp_factor *
|
||||
(pow(s1, 2) + pow(s1, -2) + pow(s2, 2) + pow(s2, -2) + pow(s3, 2) + pow(s3, -2)));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::LOG_ARAP:
|
||||
{
|
||||
energy += areas(i) * (pow(log(s1), 2) + pow(log(std::abs(s2)), 2) + pow(log(std::abs(s3)), 2));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::CONFORMAL:
|
||||
{
|
||||
energy += areas(i) * ((pow(s1, 2) + pow(s2, 2) + pow(s3, 2)) / (3 * pow(s1 * s2 * s3, 2. / 3.)));
|
||||
break;
|
||||
}
|
||||
case igl::MappingEnergyType::EXP_CONFORMAL:
|
||||
{
|
||||
energy += areas(i) * exp((pow(s1, 2) + pow(s2, 2) + pow(s3, 2)) / (3 * pow(s1 * s2 * s3, 2. / 3.)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return energy;
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Zhongshi Jiang <jiangzs@nyu.edu>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_MAPPING_ENERGY_WITH_JACOBIANS_H
|
||||
#define IGL_MAPPING_ENERGY_WITH_JACOBIANS_H
|
||||
|
||||
#include "igl_inline.h"
|
||||
#include <Eigen/Dense>
|
||||
#include "MappingEnergyType.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// compute the rotation-invariant energy of a mapping (represented in Jacobians and areas)
|
||||
// Input:
|
||||
// Ji: #F by 4 (9 if 3D) entries of jacobians
|
||||
// areas: #F by 1 face areas
|
||||
// slim_energy: energy type as in igl::MappingEnergyType
|
||||
// exp_factor: see igl::MappingEnergyType
|
||||
//
|
||||
// Output:
|
||||
// energy value
|
||||
IGL_INLINE double mapping_energy_with_jacobians(const Eigen::MatrixXd &Ji,
|
||||
const Eigen::VectorXd &areas,
|
||||
igl::MappingEnergyType slim_energy,
|
||||
double exp_factor);
|
||||
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "mapping_energy_with_jacobians.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Francis Williams <francis@fwilliams.info>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "marching_tets.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF,
|
||||
typename DerivedJ,
|
||||
typename BCType>
|
||||
void igl::marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& isovals,
|
||||
double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedSV>& outV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& outF,
|
||||
Eigen::PlainObjectBase<DerivedJ>& J,
|
||||
Eigen::SparseMatrix<BCType>& BC)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// We're hashing edges to deduplicate using 64 bit ints. The upper and lower
|
||||
// 32 bits of a key are the indices of vertices in the mesh. The implication is
|
||||
// that you can only have 2^32 vertices which I have deemed sufficient for
|
||||
// anything reasonable.
|
||||
const auto make_edge_key = [](const pair<int32_t, int32_t>& p) -> int64_t
|
||||
{
|
||||
std::int64_t ret = 0;
|
||||
ret |= p.first;
|
||||
ret |= static_cast<std::int64_t>(p.second) << 32;
|
||||
return ret;
|
||||
};
|
||||
|
||||
const int mt_cell_lookup[16][4] =
|
||||
{
|
||||
{ -1, -1, -1, -1 },
|
||||
{ 0, 2, 1, -1 },
|
||||
{ 0, 3, 4, -1 },
|
||||
{ 2, 1, 3, 4 },
|
||||
{ 5, 3, 1, -1 },
|
||||
{ 0, 2, 5, 3 },
|
||||
{ 0, 1, 5, 4 },
|
||||
{ 2, 5, 4, -1 },
|
||||
{ 4, 5, 2, -1 },
|
||||
{ 0, 4, 5, 1 },
|
||||
{ 0, 3, 5, 2 },
|
||||
{ 1, 3, 5, -1 },
|
||||
{ 4, 3, 1, 2 },
|
||||
{ 0, 4, 3, -1 },
|
||||
{ 0, 1, 2, -1 },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
const int mt_edge_lookup[6][2] =
|
||||
{
|
||||
{0, 1},
|
||||
{0, 2},
|
||||
{0, 3},
|
||||
{1, 2},
|
||||
{1, 3},
|
||||
{2, 3},
|
||||
};
|
||||
|
||||
// Store the faces and the tet they are in
|
||||
vector<pair<Eigen::RowVector3i, int>> faces;
|
||||
|
||||
// Store the edges in the tet mesh which we add vertices on
|
||||
// so we can deduplicate
|
||||
vector<pair<int, int>> edge_table;
|
||||
|
||||
|
||||
assert(TT.cols() == 4 && TT.rows() >= 1);
|
||||
assert(TV.cols() == 3 && TV.rows() >= 4);
|
||||
assert(isovals.cols() == 1);
|
||||
|
||||
// For each tet
|
||||
for (int i = 0; i < TT.rows(); i++)
|
||||
{
|
||||
uint8_t key = 0;
|
||||
for (int v = 0; v < 4; v++)
|
||||
{
|
||||
const int vid = TT(i, v);
|
||||
const uint8_t flag = isovals[vid] > isovalue;
|
||||
key |= flag << v;
|
||||
}
|
||||
|
||||
// This will contain the index in TV of each vertex in the tet
|
||||
int v_ids[4] = {-1, -1, -1, -1};
|
||||
|
||||
// Insert any vertices if the tet intersects the level surface
|
||||
for (int e = 0; e < 4 && mt_cell_lookup[key][e] != -1; e++)
|
||||
{
|
||||
const int tv1_idx = TT(i, mt_edge_lookup[mt_cell_lookup[key][e]][0]);
|
||||
const int tv2_idx = TT(i, mt_edge_lookup[mt_cell_lookup[key][e]][1]);
|
||||
const int vertex_id = edge_table.size();
|
||||
edge_table.push_back(make_pair(min(tv1_idx, tv2_idx), max(tv1_idx, tv2_idx)));
|
||||
v_ids[e] = vertex_id;
|
||||
}
|
||||
|
||||
// Insert the corresponding faces
|
||||
if (v_ids[0] != -1)
|
||||
{
|
||||
bool is_quad = mt_cell_lookup[key][3] != -1;
|
||||
if (is_quad)
|
||||
{
|
||||
const Eigen::RowVector3i f1(v_ids[0], v_ids[1], v_ids[3]);
|
||||
const Eigen::RowVector3i f2(v_ids[1], v_ids[2], v_ids[3]);
|
||||
faces.push_back(make_pair(f1, i));
|
||||
faces.push_back(make_pair(f2, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
const Eigen::RowVector3i f(v_ids[0], v_ids[1], v_ids[2]);
|
||||
faces.push_back(make_pair(f, i));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int num_unique = 0;
|
||||
outV.resize(edge_table.size(), 3);
|
||||
outF.resize(faces.size(), 3);
|
||||
J.resize(faces.size());
|
||||
|
||||
// Sparse matrix triplets for BC
|
||||
vector<Eigen::Triplet<BCType>> bc_triplets;
|
||||
bc_triplets.reserve(edge_table.size());
|
||||
|
||||
// Deduplicate vertices
|
||||
unordered_map<int64_t, int> emap;
|
||||
emap.max_load_factor(0.5);
|
||||
emap.reserve(edge_table.size());
|
||||
|
||||
for (int f = 0; f < faces.size(); f++)
|
||||
{
|
||||
for (int v = 0; v < 3; v++)
|
||||
{
|
||||
const int vi = faces[f].first[v];
|
||||
const int ti = faces[f].second;
|
||||
const pair<int32_t, int32_t> edge = edge_table[vi];
|
||||
const int64_t key = make_edge_key(edge);
|
||||
auto it = emap.find(key);
|
||||
if (it == emap.end()) // New unique vertex, insert it
|
||||
{
|
||||
// Typedef to make sure we handle floats properly
|
||||
typedef Eigen::Matrix<typename DerivedTV::Scalar, 1, 3, Eigen::RowMajor, 1, 3> RowVector;
|
||||
const RowVector v1 = TV.row(edge.first);
|
||||
const RowVector v2 = TV.row(edge.second);
|
||||
const double a = fabs(isovals[edge.first] - isovalue);
|
||||
const double b = fabs(isovals[edge.second] - isovalue);
|
||||
const double w = a / (a+b);
|
||||
|
||||
// Create a casted copy in case BCType is a float and we need to downcast
|
||||
const BCType bc_w = static_cast<BCType>(w);
|
||||
bc_triplets.push_back(Eigen::Triplet<BCType>(num_unique, edge.first, 1-bc_w));
|
||||
bc_triplets.push_back(Eigen::Triplet<BCType>(num_unique, edge.second, bc_w));
|
||||
|
||||
// Create a casted copy in case DerivedTV::Scalar is a float and we need to downcast
|
||||
const typename DerivedTV::Scalar v_w = static_cast<typename DerivedTV::Scalar>(w);
|
||||
outV.row(num_unique) = (1-v_w)*v1 + v_w*v2;
|
||||
outF(f, v) = num_unique;
|
||||
J[f] = ti;
|
||||
|
||||
emap.emplace(key, num_unique);
|
||||
num_unique += 1;
|
||||
} else {
|
||||
outF(f, v) = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
outV.conservativeResize(num_unique, 3);
|
||||
J.conservativeResize(num_unique, 1);
|
||||
BC.resize(num_unique, TV.rows());
|
||||
BC.setFromTriplets(bc_triplets.begin(), bc_triplets.end());
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template void igl::marching_tets<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::SparseMatrix<double, 0, int>&);
|
||||
#endif // IGL_STATIC_LIBRARY
|
||||
@@ -0,0 +1,196 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Francis Williams <francis@fwilliams.info>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef IGL_MARCHING_TETS_H
|
||||
#define IGL_MARCHING_TETS_H
|
||||
|
||||
#include "igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Sparse>
|
||||
|
||||
namespace igl {
|
||||
// marching_tets( TV, TT, S, isovalue, SV, SF, J, BC)
|
||||
//
|
||||
// performs the marching tetrahedra algorithm on a tet mesh defined by TV and
|
||||
// TT with scalar values defined at each vertex in TV. The output is a
|
||||
// triangle mesh approximating the isosurface coresponding to the value
|
||||
// isovalue.
|
||||
//
|
||||
// Input:
|
||||
// TV #tet_vertices x 3 array -- The vertices of the tetrahedral mesh
|
||||
// TT #tets x 4 array -- The indexes of each tet in the tetrahedral mesh
|
||||
// S #tet_vertices x 1 array -- The values defined on each tet vertex
|
||||
// isovalue scalar -- The isovalue of the level set we want to compute
|
||||
//
|
||||
// Output:
|
||||
// SV #SV x 3 array -- The vertices of the output level surface mesh
|
||||
// SF #SF x 3 array -- The face indexes of the output level surface mesh
|
||||
// J #SF list of indices into TT revealing which tet each face comes from
|
||||
// BC #SV x #TV list of barycentric coordinates so that SV = BC*TV
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF,
|
||||
typename DerivedJ,
|
||||
typename BCType>
|
||||
IGL_INLINE void marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& S,
|
||||
double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedSV>& SV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& SF,
|
||||
Eigen::PlainObjectBase<DerivedJ>& J,
|
||||
Eigen::SparseMatrix<BCType>& BC);
|
||||
|
||||
// marching_tets( TV, TT, S, SV, SF, J, BC)
|
||||
//
|
||||
// Performs the marching tetrahedra algorithm on a tet mesh defined by TV and
|
||||
// TT with scalar values defined at each vertex in TV. The output is a
|
||||
// triangle mesh approximating the isosurface coresponding to an isovalue of 0.
|
||||
//
|
||||
// Input:
|
||||
// TV #tet_vertices x 3 array -- The vertices of the tetrahedral mesh
|
||||
// TT #tets x 4 array -- The indexes of each tet in the tetrahedral mesh
|
||||
// S #tet_vertices x 1 array -- The values defined on each tet vertex
|
||||
// isovalue scalar -- The isovalue of the level set we want to compute
|
||||
//
|
||||
// Output:
|
||||
// SV #SV x 3 array -- The vertices of the output level surface mesh
|
||||
// SF #SF x 3 array -- The face indexes of the output level surface mesh
|
||||
// J #SF list of indices into TT revealing which tet each face comes from
|
||||
// BC #SV x #TV list of barycentric coordinates so that SV = BC*TV
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF,
|
||||
typename DerivedJ,
|
||||
typename BCType>
|
||||
IGL_INLINE void marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& S,
|
||||
Eigen::PlainObjectBase<DerivedSV>& SV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& SF,
|
||||
Eigen::PlainObjectBase<DerivedJ>& J,
|
||||
Eigen::SparseMatrix<BCType>& BC) {
|
||||
return igl::marching_tets(TV, TT, S, 0.0, SV, SF, J, BC);
|
||||
}
|
||||
|
||||
// marching_tets( TV, TT, S, isovalue, SV, SF, J)
|
||||
//
|
||||
// performs the marching tetrahedra algorithm on a tet mesh defined by TV and
|
||||
// TT with scalar values defined at each vertex in TV. The output is a
|
||||
// triangle mesh approximating the isosurface coresponding to the value
|
||||
// isovalue.
|
||||
//
|
||||
// Input:
|
||||
// TV #tet_vertices x 3 array -- The vertices of the tetrahedral mesh
|
||||
// TT #tets x 4 array -- The indexes of each tet in the tetrahedral mesh
|
||||
// S #tet_vertices x 1 array -- The values defined on each tet vertex
|
||||
// isovalue scalar -- The isovalue of the level set we want to compute
|
||||
//
|
||||
// Output:
|
||||
// SV #SV x 3 array -- The vertices of the output level surface mesh
|
||||
// SF #SF x 3 array -- The face indexes of the output level surface mesh
|
||||
// J #SF list of indices into TT revealing which tet each face comes from
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF,
|
||||
typename DerivedJ>
|
||||
IGL_INLINE void marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& S,
|
||||
double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedSV>& SV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& SF,
|
||||
Eigen::PlainObjectBase<DerivedJ>& J) {
|
||||
Eigen::SparseMatrix<double> _BC;
|
||||
return igl::marching_tets(TV, TT, S, isovalue, SV, SF, J, _BC);
|
||||
}
|
||||
|
||||
// marching_tets( TV, TT, S, isovalue, SV, SF, BC)
|
||||
//
|
||||
// performs the marching tetrahedra algorithm on a tet mesh defined by TV and
|
||||
// TT with scalar values defined at each vertex in TV. The output is a
|
||||
// triangle mesh approximating the isosurface coresponding to the value
|
||||
// isovalue.
|
||||
//
|
||||
// Input:
|
||||
// TV #tet_vertices x 3 array -- The vertices of the tetrahedral mesh
|
||||
// TT #tets x 4 array -- The indexes of each tet in the tetrahedral mesh
|
||||
// S #tet_vertices x 1 array -- The values defined on each tet vertex
|
||||
// isovalue scalar -- The isovalue of the level set we want to compute
|
||||
//
|
||||
// Output:
|
||||
// SV #SV x 3 array -- The vertices of the output level surface mesh
|
||||
// SF #SF x 3 array -- The face indexes of the output level surface mesh
|
||||
// BC #SV x #TV list of barycentric coordinates so that SV = BC*TV
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF,
|
||||
typename BCType>
|
||||
IGL_INLINE void marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& S,
|
||||
double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedSV>& SV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& SF,
|
||||
Eigen::SparseMatrix<BCType>& BC) {
|
||||
Eigen::VectorXi _J;
|
||||
return igl::marching_tets(TV, TT, S, isovalue, SV, SF, _J, BC);
|
||||
}
|
||||
|
||||
// marching_tets( TV, TT, S, isovalue, SV, SF)
|
||||
//
|
||||
// performs the marching tetrahedra algorithm on a tet mesh defined by TV and
|
||||
// TT with scalar values defined at each vertex in TV. The output is a
|
||||
// triangle mesh approximating the isosurface coresponding to the value
|
||||
// isovalue.
|
||||
//
|
||||
// Input:
|
||||
// TV #tet_vertices x 3 array -- The vertices of the tetrahedral mesh
|
||||
// TT #tets x 4 array -- The indexes of each tet in the tetrahedral mesh
|
||||
// S #tet_vertices x 1 array -- The values defined on each tet vertex
|
||||
// isovalue scalar -- The isovalue of the level set we want to compute
|
||||
//
|
||||
// Output:
|
||||
// SV #SV x 3 array -- The vertices of the output level surface mesh
|
||||
// SF #SF x 3 array -- The face indexes of the output level surface mesh
|
||||
template <typename DerivedTV,
|
||||
typename DerivedTT,
|
||||
typename DerivedS,
|
||||
typename DerivedSV,
|
||||
typename DerivedSF>
|
||||
IGL_INLINE void marching_tets(
|
||||
const Eigen::PlainObjectBase<DerivedTV>& TV,
|
||||
const Eigen::PlainObjectBase<DerivedTT>& TT,
|
||||
const Eigen::PlainObjectBase<DerivedS>& S,
|
||||
double isovalue,
|
||||
Eigen::PlainObjectBase<DerivedSV>& SV,
|
||||
Eigen::PlainObjectBase<DerivedSF>& SF) {
|
||||
Eigen::VectorXi _J;
|
||||
Eigen::SparseMatrix<double> _BC;
|
||||
return igl::marching_tets(TV, TT, S, isovalue, SV, SF, _J, _BC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "marching_tets.cpp"
|
||||
#endif
|
||||
|
||||
#endif // IGL_MARCHING_TETS_H
|
||||
@@ -35,7 +35,7 @@ namespace igl
|
||||
// Scalar scalar type for eigen sparse matrix (e.g. double)
|
||||
// Inputs:
|
||||
// V #V by dim list of mesh vertex positions
|
||||
// F #F by simplex_size list of mesh faces (must be triangles)
|
||||
// F #F by simplex_size list of mesh elements (triangles or tetrahedra)
|
||||
// type one of the following ints:
|
||||
// MASSMATRIX_TYPE_BARYCENTRIC barycentric
|
||||
// MASSMATRIX_TYPE_VORONOI voronoi-hybrid {default}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "median.h"
|
||||
#include "matrix_to_list.h"
|
||||
@@ -42,4 +42,5 @@ IGL_INLINE bool igl::median(
|
||||
template bool igl::median<Eigen::Block<Eigen::Matrix<float, -1, -1, 0, -1, -1>, -1, 1, true>, float>(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<float, -1, -1, 0, -1, -1>, -1, 1, true> > const&, float&);
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::median<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, true>, double>(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, true> > const&, double&);
|
||||
template bool igl::median<Eigen::Matrix<double, -1, 1, 0, -1, 1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, double&);
|
||||
#endif
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace igl {
|
||||
std::function< void(const ChildrenType, const int) > helper;
|
||||
helper = [&helper,&translate_center,&get_octant,&m,
|
||||
&zero_to_seven,&neg_ones,&P,
|
||||
&point_indices,&children,¢ers,&widths]
|
||||
&point_indices,&children,¢ers,&widths,&MAX_DEPTH]
|
||||
(const ChildrenType index, const int depth)-> void
|
||||
{
|
||||
if(point_indices.at(index).size() > 1 && depth < MAX_DEPTH){
|
||||
@@ -173,4 +173,8 @@ namespace igl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::octree<Eigen::Matrix<double, -1, -1, 0, -1, -1>, int, Eigen::Matrix<int, -1, 8, 0, -1, 8>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
|
||||
@@ -112,7 +112,7 @@ IGL_INLINE void igl::opengl::ViewerCore::draw(
|
||||
/* Bind and potentially refresh mesh/line/point data */
|
||||
if (data.dirty)
|
||||
{
|
||||
data.updateGL(data, data.invert_normals,data.meshgl);
|
||||
data.updateGL(data, data.invert_normals, data.meshgl);
|
||||
data.dirty = MeshGL::DIRTY_NONE;
|
||||
}
|
||||
data.meshgl.bind_mesh();
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace glfw
|
||||
#ifdef __APPLE__
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||
#endif
|
||||
if(fullscreen)
|
||||
{
|
||||
@@ -477,10 +478,6 @@ namespace glfw
|
||||
|
||||
IGL_INLINE bool Viewer::key_pressed(unsigned int unicode_key,int modifiers)
|
||||
{
|
||||
if (callback_key_pressed)
|
||||
if (callback_key_pressed(*this,unicode_key,modifiers))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
{
|
||||
if (plugins[i]->key_pressed(unicode_key, modifiers))
|
||||
@@ -489,6 +486,10 @@ namespace glfw
|
||||
}
|
||||
}
|
||||
|
||||
if (callback_key_pressed)
|
||||
if (callback_key_pressed(*this,unicode_key,modifiers))
|
||||
return true;
|
||||
|
||||
switch(unicode_key)
|
||||
{
|
||||
case 'A':
|
||||
@@ -563,25 +564,27 @@ namespace glfw
|
||||
|
||||
IGL_INLINE bool Viewer::key_down(int key,int modifiers)
|
||||
{
|
||||
if (callback_key_down)
|
||||
if (callback_key_down(*this,key,modifiers))
|
||||
return true;
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if (plugins[i]->key_down(key, modifiers))
|
||||
return true;
|
||||
|
||||
if (callback_key_down)
|
||||
if (callback_key_down(*this,key,modifiers))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IGL_INLINE bool Viewer::key_up(int key,int modifiers)
|
||||
{
|
||||
if (callback_key_up)
|
||||
if (callback_key_up(*this,key,modifiers))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if (plugins[i]->key_up(key, modifiers))
|
||||
return true;
|
||||
|
||||
if (callback_key_up)
|
||||
if (callback_key_up(*this,key,modifiers))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -591,14 +594,14 @@ namespace glfw
|
||||
down_mouse_x = current_mouse_x;
|
||||
down_mouse_y = current_mouse_y;
|
||||
|
||||
if (callback_mouse_down)
|
||||
if (callback_mouse_down(*this,static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if(plugins[i]->mouse_down(static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
if (callback_mouse_down)
|
||||
if (callback_mouse_down(*this,static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
down = true;
|
||||
|
||||
down_translation = core.camera_translation;
|
||||
@@ -651,14 +654,14 @@ namespace glfw
|
||||
{
|
||||
down = false;
|
||||
|
||||
if (callback_mouse_up)
|
||||
if (callback_mouse_up(*this,static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if(plugins[i]->mouse_up(static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
if (callback_mouse_up)
|
||||
if (callback_mouse_up(*this,static_cast<int>(button),modifier))
|
||||
return true;
|
||||
|
||||
mouse_mode = MouseMode::None;
|
||||
|
||||
return true;
|
||||
@@ -675,14 +678,14 @@ namespace glfw
|
||||
current_mouse_x = mouse_x;
|
||||
current_mouse_y = mouse_y;
|
||||
|
||||
if (callback_mouse_move)
|
||||
if (callback_mouse_move(*this,mouse_x,mouse_y))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if (plugins[i]->mouse_move(mouse_x, mouse_y))
|
||||
return true;
|
||||
|
||||
if (callback_mouse_move)
|
||||
if (callback_mouse_move(*this,mouse_x,mouse_y))
|
||||
return true;
|
||||
|
||||
if (down)
|
||||
{
|
||||
switch (mouse_mode)
|
||||
@@ -752,14 +755,14 @@ namespace glfw
|
||||
{
|
||||
scroll_position += delta_y;
|
||||
|
||||
if (callback_mouse_scroll)
|
||||
if (callback_mouse_scroll(*this,delta_y))
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if (plugins[i]->mouse_scroll(delta_y))
|
||||
return true;
|
||||
|
||||
if (callback_mouse_scroll)
|
||||
if (callback_mouse_scroll(*this,delta_y))
|
||||
return true;
|
||||
|
||||
// Only zoom if there's actually a change
|
||||
if(delta_y != 0)
|
||||
{
|
||||
@@ -821,16 +824,16 @@ namespace glfw
|
||||
}
|
||||
|
||||
core.clear_framebuffers();
|
||||
if (callback_pre_draw)
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
{
|
||||
if (callback_pre_draw(*this))
|
||||
if (plugins[i]->pre_draw())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
if (callback_pre_draw)
|
||||
{
|
||||
if (plugins[i]->pre_draw())
|
||||
if (callback_pre_draw(*this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -839,13 +842,6 @@ namespace glfw
|
||||
{
|
||||
core.draw(data_list[i]);
|
||||
}
|
||||
if (callback_post_draw)
|
||||
{
|
||||
if (callback_post_draw(*this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i<plugins.size(); ++i)
|
||||
{
|
||||
if (plugins[i]->post_draw())
|
||||
@@ -853,6 +849,13 @@ namespace glfw
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (callback_post_draw)
|
||||
{
|
||||
if (callback_post_draw(*this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGL_INLINE void Viewer::resize(int w,int h)
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#define IGL_OPENGL_GLFW_IMGUI_IMGUIHELPERS_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include "ImGuiTraits.h"
|
||||
#include <imgui/imgui.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Extend ImGui by populating its namespace directly
|
||||
@@ -25,35 +27,35 @@ namespace ImGui
|
||||
|
||||
static auto vector_getter = [](void* vec, int idx, const char** out_text)
|
||||
{
|
||||
auto& vector = *static_cast<std::vector<std::string>*>(vec);
|
||||
if (idx < 0 || idx >= static_cast<int>(vector.size())) { return false; }
|
||||
*out_text = vector.at(idx).c_str();
|
||||
return true;
|
||||
auto& vector = *static_cast<std::vector<std::string>*>(vec);
|
||||
if (idx < 0 || idx >= static_cast<int>(vector.size())) { return false; }
|
||||
*out_text = vector.at(idx).c_str();
|
||||
return true;
|
||||
};
|
||||
|
||||
inline bool Combo(const char* label, int* idx, std::vector<std::string>& values)
|
||||
{
|
||||
if (values.empty()) { return false; }
|
||||
return Combo(label, idx, vector_getter,
|
||||
static_cast<void*>(&values), values.size());
|
||||
if (values.empty()) { return false; }
|
||||
return Combo(label, idx, vector_getter,
|
||||
static_cast<void*>(&values), values.size());
|
||||
}
|
||||
|
||||
inline bool Combo(const char* label, int* idx, std::function<const char *(int)> getter, int items_count)
|
||||
{
|
||||
auto func = [](void* data, int i, const char** out_text) {
|
||||
auto &getter = *reinterpret_cast<std::function<const char *(int)> *>(data);
|
||||
const char *s = getter(i);
|
||||
if (s) { *out_text = s; return true; }
|
||||
else { return false; }
|
||||
};
|
||||
return Combo(label, idx, func, reinterpret_cast<void *>(&getter), items_count);
|
||||
auto func = [](void* data, int i, const char** out_text) {
|
||||
auto &getter = *reinterpret_cast<std::function<const char *(int)> *>(data);
|
||||
const char *s = getter(i);
|
||||
if (s) { *out_text = s; return true; }
|
||||
else { return false; }
|
||||
};
|
||||
return Combo(label, idx, func, reinterpret_cast<void *>(&getter), items_count);
|
||||
}
|
||||
|
||||
inline bool ListBox(const char* label, int* idx, std::vector<std::string>& values)
|
||||
{
|
||||
if (values.empty()) { return false; }
|
||||
return ListBox(label, idx, vector_getter,
|
||||
static_cast<void*>(&values), values.size());
|
||||
if (values.empty()) { return false; }
|
||||
return ListBox(label, idx, vector_getter,
|
||||
static_cast<void*>(&values), values.size());
|
||||
}
|
||||
|
||||
inline bool InputText(const char* label, std::string &str, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL)
|
||||
@@ -69,6 +71,36 @@ inline bool InputText(const char* label, std::string &str, ImGuiInputTextFlags f
|
||||
return false;
|
||||
}
|
||||
|
||||
// template<typename T>
|
||||
// inline bool DragScalar(const char *label, T* value, void* v, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f)
|
||||
// {
|
||||
// const char *fmt = format;
|
||||
// if (format == nullptr) {
|
||||
// fmt = ImGuiDataTypeTraits<T>::format;
|
||||
// }
|
||||
// return DragScalar(label, ImGuiDataTypeTraits<T>::value, value, &min, &max, fmt);
|
||||
// }
|
||||
|
||||
// template<typename T>
|
||||
// inline bool InputScalar(const char *label, T* value, T min = 0, T max = 0, const char* format = nulltptr)
|
||||
// {
|
||||
// const char *fmt = format;
|
||||
// if (format == nullptr) {
|
||||
// fmt = ImGuiDataTypeTraits<T>::format;
|
||||
// }
|
||||
// return InputScalar(label, ImGuiDataTypeTraits<T>::value, value, &min, &max, fmt);
|
||||
// }
|
||||
|
||||
template<typename T>
|
||||
inline bool SliderScalar(const char *label, T* value, T min = 0, T max = 0, const char* format = "")
|
||||
{
|
||||
const char *fmt = format;
|
||||
if (format == nullptr) {
|
||||
fmt = ImGuiDataTypeTraits<T>::format;
|
||||
}
|
||||
return SliderScalar(label, ImGuiDataTypeTraits<T>::value, value, &min, &max, fmt);
|
||||
}
|
||||
|
||||
} // namespace ImGui
|
||||
|
||||
#endif // IGL_OPENGL_GLFW_IMGUI_IMGUIHELPERS_H
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#include "ImGuiMenu.h"
|
||||
#include <igl/project.h>
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui_impl_glfw_gl3.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <imgui_fonts_droid_sans.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
@@ -30,11 +31,16 @@ IGL_INLINE void ImGuiMenu::init(igl::opengl::glfw::Viewer *_viewer)
|
||||
// Setup ImGui binding
|
||||
if (_viewer)
|
||||
{
|
||||
if (context_ == nullptr)
|
||||
IMGUI_CHECKVERSION();
|
||||
if (!context_)
|
||||
{
|
||||
context_ = ImGui::CreateContext();
|
||||
// Single global context by default, but can be overridden by the user
|
||||
static ImGuiContext * __global_context = ImGui::CreateContext();
|
||||
context_ = __global_context;
|
||||
}
|
||||
ImGui_ImplGlfwGL3_Init(viewer->window, false);
|
||||
const char* glsl_version = "#version 150";
|
||||
ImGui_ImplGlfw_InitForOpenGL(viewer->window, false);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
ImGui::StyleColorsDark();
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
@@ -57,9 +63,10 @@ IGL_INLINE void ImGuiMenu::reload_font(int font_size)
|
||||
IGL_INLINE void ImGuiMenu::shutdown()
|
||||
{
|
||||
// Cleanup
|
||||
ImGui_ImplGlfwGL3_Shutdown();
|
||||
ImGui::DestroyContext(context_);
|
||||
context_ = nullptr;
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
// User is responsible for destroying context if a custom context is given
|
||||
// ImGui::DestroyContext(*context_);
|
||||
}
|
||||
|
||||
IGL_INLINE bool ImGuiMenu::pre_draw()
|
||||
@@ -71,10 +78,12 @@ IGL_INLINE bool ImGuiMenu::pre_draw()
|
||||
if (std::abs(scaling - hidpi_scaling_) > 1e-5)
|
||||
{
|
||||
reload_font();
|
||||
ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
|
||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
ImGui_ImplGlfwGL3_NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,6 +91,7 @@ IGL_INLINE bool ImGuiMenu::post_draw()
|
||||
{
|
||||
draw_menu();
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -97,7 +107,7 @@ IGL_INLINE void ImGuiMenu::post_resize(int width, int height)
|
||||
// Mouse IO
|
||||
IGL_INLINE bool ImGuiMenu::mouse_down(int button, int modifier)
|
||||
{
|
||||
ImGui_ImplGlfwGL3_MouseButtonCallback(viewer->window, button, GLFW_PRESS, modifier);
|
||||
ImGui_ImplGlfw_MouseButtonCallback(viewer->window, button, GLFW_PRESS, modifier);
|
||||
return ImGui::GetIO().WantCaptureMouse;
|
||||
}
|
||||
|
||||
@@ -113,26 +123,26 @@ IGL_INLINE bool ImGuiMenu::mouse_move(int mouse_x, int mouse_y)
|
||||
|
||||
IGL_INLINE bool ImGuiMenu::mouse_scroll(float delta_y)
|
||||
{
|
||||
ImGui_ImplGlfwGL3_ScrollCallback(viewer->window, 0.f, delta_y);
|
||||
ImGui_ImplGlfw_ScrollCallback(viewer->window, 0.f, delta_y);
|
||||
return ImGui::GetIO().WantCaptureMouse;
|
||||
}
|
||||
|
||||
// Keyboard IO
|
||||
IGL_INLINE bool ImGuiMenu::key_pressed(unsigned int key, int modifiers)
|
||||
{
|
||||
ImGui_ImplGlfwGL3_CharCallback(nullptr, key);
|
||||
ImGui_ImplGlfw_CharCallback(nullptr, key);
|
||||
return ImGui::GetIO().WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
IGL_INLINE bool ImGuiMenu::key_down(int key, int modifiers)
|
||||
{
|
||||
ImGui_ImplGlfwGL3_KeyCallback(viewer->window, key, 0, GLFW_PRESS, modifiers);
|
||||
ImGui_ImplGlfw_KeyCallback(viewer->window, key, 0, GLFW_PRESS, modifiers);
|
||||
return ImGui::GetIO().WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
IGL_INLINE bool ImGuiMenu::key_up(int key, int modifiers)
|
||||
{
|
||||
ImGui_ImplGlfwGL3_KeyCallback(viewer->window, key, 0, GLFW_RELEASE, modifiers);
|
||||
ImGui_ImplGlfw_KeyCallback(viewer->window, key, 0, GLFW_RELEASE, modifiers);
|
||||
return ImGui::GetIO().WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
@@ -256,7 +266,7 @@ IGL_INLINE void ImGuiMenu::draw_viewer_menu()
|
||||
{
|
||||
if (ImGui::Checkbox("Face-based", &(viewer->data().face_based)))
|
||||
{
|
||||
viewer->data().set_face_based(viewer->data().face_based);
|
||||
viewer->data().dirty = MeshGL::DIRTY_ALL;
|
||||
}
|
||||
ImGui::Checkbox("Show texture", &(viewer->data().show_texture));
|
||||
if (ImGui::Checkbox("Invert normals", &(viewer->data().invert_normals)))
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <igl/opengl/glfw/Viewer.h>
|
||||
#include <igl/opengl/glfw/ViewerPlugin.h>
|
||||
#include <igl/igl_inline.h>
|
||||
#include <memory>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Forward declarations
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2018 Jérémie Dumas <jeremie.dumas@ens-lyon.org>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL_GLFW_IMGUI_IMGUITRAITS_H
|
||||
#define IGL_OPENGL_GLFW_IMGUI_IMGUITRAITS_H
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
// Extend ImGui by populating its namespace directly
|
||||
namespace ImGui
|
||||
{
|
||||
|
||||
// Infer ImGuiDataType enum based on actual type
|
||||
template<typename T>
|
||||
class ImGuiDataTypeTraits
|
||||
{
|
||||
static const ImGuiDataType value; // link error
|
||||
static const char * format;
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<int>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_S32;
|
||||
static constexpr char * format = "%d";
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<unsigned int>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_U32;
|
||||
static constexpr char * format = "%u";
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<long long>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_S64;
|
||||
static constexpr char * format = "%lld";
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<unsigned long long>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_U64;
|
||||
static constexpr char * format = "%llu";
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<float>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_Float;
|
||||
static constexpr char * format = "%.3f";
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImGuiDataTypeTraits<double>
|
||||
{
|
||||
static constexpr ImGuiDataType value = ImGuiDataType_Double;
|
||||
static constexpr char * format = "%.6f";
|
||||
};
|
||||
|
||||
} // namespace ImGui
|
||||
|
||||
#endif // IGL_OPENGL_GLFW_IMGUI_IMGUIHELPERS_H
|
||||
@@ -1,691 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_MOUSECONTROLLER_H
|
||||
#define IGL_OPENGL2_MOUSECONTROLLER_H
|
||||
// Needs to be included before others
|
||||
#include <Eigen/StdVector>
|
||||
#include "RotateWidget.h"
|
||||
#include "TranslateWidget.h"
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
#include <vector>
|
||||
|
||||
// Class for control a skeletal FK rig with the mouse.
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
class MouseController
|
||||
{
|
||||
public:
|
||||
typedef Eigen::VectorXi VectorXb;
|
||||
// Propagate selection to descendants so that selected bones and their
|
||||
// subtrees are all selected.
|
||||
//
|
||||
// Input:
|
||||
// S #S list of whether selected
|
||||
// P #S list of bone parents
|
||||
// Output:
|
||||
// T #S list of whether selected
|
||||
static inline void propogate_to_descendants_if(
|
||||
const VectorXb & S,
|
||||
const Eigen::VectorXi & P,
|
||||
VectorXb & T);
|
||||
// Create a matrix of colors for the selection and their descendants.
|
||||
//
|
||||
// Inputs:
|
||||
// selection #S list of whether a bone is selected
|
||||
// selected_color color for selected bones
|
||||
// unselected_color color for unselected bones
|
||||
// Outputs:
|
||||
// C #P by 4 list of colors
|
||||
static inline void color_if(
|
||||
const VectorXb & S,
|
||||
const Eigen::Vector4f & selected_color,
|
||||
const Eigen::Vector4f & unselected_color,
|
||||
Eigen::MatrixXf & C);
|
||||
enum WidgetMode
|
||||
{
|
||||
WIDGET_MODE_ROTATE = 0,
|
||||
WIDGET_MODE_TRANSLATE = 1,
|
||||
NUM_WIDGET_MODES = 2,
|
||||
};
|
||||
private:
|
||||
// m_is_selecting whether currently selecting
|
||||
// m_selection #m_rotations list of whether a bone is selected
|
||||
// m_down_x x-coordinate of mouse location at down
|
||||
// m_down_y y-coordinate 〃
|
||||
// m_drag_x x-coordinate of mouse location at drag
|
||||
// m_drag_y y-coordinate 〃
|
||||
// m_widget rotation widget for selected bone
|
||||
// m_width width of containing window
|
||||
// m_height height 〃
|
||||
// m_rotations list of rotations for each bone
|
||||
// m_rotations_at_selection list of rotations for each bone at time of
|
||||
// selection
|
||||
// m_translations list of translations for each bone
|
||||
// m_fk_rotations_at_selection list of rotations for each bone at time of
|
||||
// selection
|
||||
// m_root_enabled Whether root is enabled
|
||||
bool m_is_selecting;
|
||||
VectorXb m_selection;
|
||||
int m_down_x,m_down_y,m_drag_x,m_drag_y;
|
||||
int m_width,m_height;
|
||||
igl::opengl2::RotateWidget m_widget;
|
||||
igl::opengl2::TranslateWidget m_trans_widget;
|
||||
Eigen::Quaterniond m_widget_rot_at_selection;
|
||||
//Eigen::Vector3d m_trans_widget_trans_at_selection;
|
||||
typedef std::vector<
|
||||
Eigen::Quaterniond,
|
||||
Eigen::aligned_allocator<Eigen::Quaterniond> > RotationList;
|
||||
typedef std::vector< Eigen::Vector3d > TranslationList;
|
||||
RotationList
|
||||
m_rotations,
|
||||
m_rotations_at_selection,
|
||||
m_fk_rotations_at_selection,
|
||||
m_parent_rotations_at_selection;
|
||||
TranslationList
|
||||
m_translations,
|
||||
m_translations_at_selection,
|
||||
m_fk_translations_at_selection;
|
||||
bool m_root_enabled;
|
||||
WidgetMode m_widget_mode;
|
||||
public:
|
||||
MouseController();
|
||||
// Returns const reference to m_selection
|
||||
inline const VectorXb & selection() const{return m_selection;};
|
||||
// 〃 m_is_selecting
|
||||
inline const bool & is_selecting() const{return m_is_selecting;}
|
||||
inline bool is_widget_down() const{return m_widget.is_down();}
|
||||
inline bool is_trans_widget_down() const{return m_trans_widget.is_down();}
|
||||
// 〃 m_rotations
|
||||
inline const RotationList & rotations() const{return m_rotations;}
|
||||
inline const TranslationList & translations() const{return m_translations;}
|
||||
// Returns non-const reference to m_root_enabled
|
||||
inline bool & root_enabled(){ return m_root_enabled;}
|
||||
inline void reshape(const int w, const int h);
|
||||
// Process down, drag, up mouse events
|
||||
//
|
||||
// Inputs:
|
||||
// x x-coordinate of mouse click with respect to container
|
||||
// y y-coordinate 〃
|
||||
// Returns true if accepted (action taken).
|
||||
inline bool down(const int x, const int y);
|
||||
inline bool drag(const int x, const int y);
|
||||
inline bool up(const int x, const int y);
|
||||
// Draw selection box and widget
|
||||
inline void draw() const;
|
||||
// Set `m_selection` based on the last drag selection and initialize
|
||||
// widget.
|
||||
//
|
||||
// Inputs:
|
||||
// C #C by dim list of joint positions at rest
|
||||
// BE #BE by 2 list of bone indices at rest
|
||||
// P #P list of bone parents
|
||||
inline void set_selection_from_last_drag(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const Eigen::VectorXi & P,
|
||||
const Eigen::VectorXi & RP);
|
||||
// Set from explicit selection
|
||||
inline void set_selection(
|
||||
const Eigen::VectorXi & S,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const Eigen::VectorXi & P,
|
||||
const Eigen::VectorXi & RP);
|
||||
// Set size of skeleton
|
||||
//
|
||||
// Inputs:
|
||||
// n number of bones
|
||||
inline void set_size(const int n);
|
||||
// Resets m_rotation elements to identity
|
||||
inline void reset();
|
||||
inline void reset_selected();
|
||||
inline void reset_rotations();
|
||||
inline void reset_selected_rotations();
|
||||
inline void reset_translations();
|
||||
inline void reset_selected_translations();
|
||||
inline bool set_rotations(const RotationList & vQ);
|
||||
inline bool set_translations(const TranslationList & vT);
|
||||
// Sets all entries in m_selection to false
|
||||
inline void clear_selection();
|
||||
// Returns true iff some element in m_selection is true
|
||||
inline bool any_selection() const;
|
||||
inline void set_widget_mode(const WidgetMode & mode);
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation
|
||||
#include "../line_segment_in_rectangle.h"
|
||||
#include "draw_rectangular_marquee.h"
|
||||
#include "project.h"
|
||||
#include "../forward_kinematics.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
inline void igl::opengl2::MouseController::propogate_to_descendants_if(
|
||||
const VectorXb & S,
|
||||
const Eigen::VectorXi & P,
|
||||
VectorXb & T)
|
||||
{
|
||||
using namespace std;
|
||||
const int n = S.rows();
|
||||
assert(P.rows() == n);
|
||||
// dynamic programming
|
||||
T = S;
|
||||
vector<bool> seen(n,false);
|
||||
// Recursively look up chain and see if ancestor is selected
|
||||
const function<bool(int)> look_up = [&](int e) -> bool
|
||||
{
|
||||
if(e==-1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!seen[e])
|
||||
{
|
||||
seen[e] = true;
|
||||
T(e) |= look_up(P(e));
|
||||
}
|
||||
return T(e);
|
||||
};
|
||||
for(int e = 0;e<n;e++)
|
||||
{
|
||||
if(!seen[e])
|
||||
{
|
||||
T(e) = look_up(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::color_if(
|
||||
const VectorXb & S,
|
||||
const Eigen::Vector4f & selected_color,
|
||||
const Eigen::Vector4f & unselected_color,
|
||||
Eigen::MatrixXf & C)
|
||||
{
|
||||
C.resize(S.rows(),4);
|
||||
for(int e=0;e<S.rows();e++)
|
||||
{
|
||||
C.row(e) = S(e)?selected_color:unselected_color;
|
||||
}
|
||||
}
|
||||
|
||||
inline igl::opengl2::MouseController::MouseController():
|
||||
m_is_selecting(false),
|
||||
m_selection(),
|
||||
m_down_x(-1),m_down_y(-1),m_drag_x(-1),m_drag_y(-1),
|
||||
m_width(-1),m_height(-1),
|
||||
m_widget(),
|
||||
m_widget_rot_at_selection(),
|
||||
//m_trans_widget_trans_at_selection(),
|
||||
m_trans_widget(),
|
||||
m_rotations(),
|
||||
m_translations(),
|
||||
m_rotations_at_selection(),
|
||||
m_root_enabled(true),
|
||||
m_widget_mode(WIDGET_MODE_ROTATE)
|
||||
{
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reshape(const int w, const int h)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::down(const int x, const int y)
|
||||
{
|
||||
using namespace std;
|
||||
m_down_x = m_drag_x =x;
|
||||
m_down_y = m_drag_y =y;
|
||||
const bool widget_down = any_selection() &&
|
||||
(
|
||||
(m_widget_mode == WIDGET_MODE_ROTATE && m_widget.down(x,m_height-y)) ||
|
||||
(m_widget_mode == WIDGET_MODE_TRANSLATE &&
|
||||
m_trans_widget.down(x,m_height-y))
|
||||
);
|
||||
if(!widget_down)
|
||||
{
|
||||
m_is_selecting = true;
|
||||
}
|
||||
return m_is_selecting || widget_down;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::drag(const int x, const int y)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
m_drag_x = x;
|
||||
m_drag_y = y;
|
||||
if(m_is_selecting)
|
||||
{
|
||||
return m_is_selecting;
|
||||
}else
|
||||
{
|
||||
switch(m_widget_mode)
|
||||
{
|
||||
default: // fall through
|
||||
case WIDGET_MODE_ROTATE:
|
||||
{
|
||||
if(!m_widget.drag(x,m_height-y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(any_selection());
|
||||
assert(m_selection.size() == (int)m_rotations.size());
|
||||
assert(m_selection.size() == (int)m_translations.size());
|
||||
for(int e = 0;e<m_selection.size();e++)
|
||||
{
|
||||
if(m_selection(e))
|
||||
{
|
||||
// Let:
|
||||
// w.θr = w.θ ⋅ w.θ₀*
|
||||
// w.θr takes (absolute) frame of w.θ₀ to w.θ:
|
||||
// w.θ = w.θr ⋅ w.θ₀
|
||||
// Define:
|
||||
// w.θ₀ = θfk ⋅ θx,
|
||||
// the absolute rotation of the x axis to the deformed bone at
|
||||
// selection. Likewise,
|
||||
// w.θ = θfk' ⋅ θx,
|
||||
// the current absolute rotation of the x axis to the deformed bone.
|
||||
// Define recursively:
|
||||
// θfk = θfk(p) ⋅ Θr,
|
||||
// then because we're only changeing this relative rotation
|
||||
// θfk' = θfk(p) ⋅ Θr ⋅ θr* ⋅ θr'
|
||||
// θfk' = θfk ⋅ θr* ⋅ θr'
|
||||
// w.θ ⋅ θx* = θfk ⋅ θr* ⋅ θr'
|
||||
// θr ⋅ θfk* ⋅ w.θ ⋅ θx* = θr'
|
||||
// θr ⋅ θfk* ⋅ w.θr ⋅ w.θ₀ ⋅ θx* = θr'
|
||||
// θr ⋅ θfk* ⋅ w.θr ⋅ θfk ⋅θx ⋅ θx* = θr'
|
||||
// θr ⋅ θfk* ⋅ w.θr ⋅ θfk = θr'
|
||||
// which I guess is the right multiply change after being changed to
|
||||
// the bases of θfk, the rotation of the bone relative to its rest
|
||||
// frame.
|
||||
//
|
||||
const Quaterniond & frame = m_fk_rotations_at_selection[e];
|
||||
m_rotations[e] =
|
||||
m_rotations_at_selection[e] *
|
||||
frame.conjugate() *
|
||||
(m_widget.rot*m_widget_rot_at_selection.conjugate()) *
|
||||
frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
case WIDGET_MODE_TRANSLATE:
|
||||
{
|
||||
if(!m_trans_widget.drag(x,m_height-y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(any_selection());
|
||||
assert(m_selection.size() == (int)m_rotations.size());
|
||||
assert(m_selection.size() == (int)m_translations.size());
|
||||
for(int e = 0;e<m_selection.size();e++)
|
||||
{
|
||||
if(m_selection(e))
|
||||
{
|
||||
m_translations[e] =
|
||||
m_translations_at_selection[e] +
|
||||
m_parent_rotations_at_selection[e].conjugate()*
|
||||
m_trans_widget.m_trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::up(const int x, const int y)
|
||||
{
|
||||
m_is_selecting = false;
|
||||
m_widget.up(x,m_height-y);
|
||||
m_trans_widget.up(x,m_height-y);
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::draw() const
|
||||
{
|
||||
if(any_selection())
|
||||
{
|
||||
switch(m_widget_mode)
|
||||
{
|
||||
default:
|
||||
case WIDGET_MODE_ROTATE:
|
||||
m_widget.draw();
|
||||
break;
|
||||
case WIDGET_MODE_TRANSLATE:
|
||||
m_trans_widget.draw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(m_is_selecting)
|
||||
{
|
||||
// Remember settings
|
||||
GLboolean dt;
|
||||
glGetBooleanv(GL_DEPTH_TEST,&dt);
|
||||
int old_vp[4];
|
||||
glGetIntegerv(GL_VIEWPORT,old_vp);
|
||||
|
||||
// True screen space
|
||||
glViewport(0,0,m_width,m_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0,m_width,0,m_height);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
draw_rectangular_marquee(
|
||||
m_down_x,
|
||||
m_height-m_down_y,
|
||||
m_drag_x,
|
||||
m_height-m_drag_y);
|
||||
|
||||
// Restore settings
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glViewport(old_vp[0],old_vp[1],old_vp[2],old_vp[3]);
|
||||
dt?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::set_selection_from_last_drag(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const Eigen::VectorXi & P,
|
||||
const Eigen::VectorXi & RP)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
m_rotations_at_selection = m_rotations;
|
||||
m_translations_at_selection = m_translations;
|
||||
assert(BE.rows() == P.rows());
|
||||
m_selection = VectorXb::Zero(BE.rows());
|
||||
// m_rotation[e] is the relative rotation stored at bone e (as seen by the
|
||||
// joint traveling with its parent)
|
||||
// vQ[e] is the absolute rotation of a bone at rest to its current position:
|
||||
// vQ[e] = vQ[p(e)] * m_rotation[e]
|
||||
vector<Quaterniond,aligned_allocator<Quaterniond> > vQ;
|
||||
vector<Vector3d> vT;
|
||||
forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
|
||||
// Loop over deformed bones
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
Affine3d a = Affine3d::Identity();
|
||||
a.translate(vT[e]);
|
||||
a.rotate(vQ[e]);
|
||||
Vector3d s = a * (Vector3d)C.row(BE(e,0));
|
||||
Vector3d d = a * (Vector3d)C.row(BE(e,1));
|
||||
Vector3d projs = project(s);
|
||||
Vector3d projd = project(d);
|
||||
m_selection(e) = line_segment_in_rectangle(
|
||||
projs.head(2),projd.head(2),
|
||||
Vector2d(m_down_x,m_height-m_down_y),
|
||||
Vector2d(m_drag_x,m_height-m_drag_y));
|
||||
}
|
||||
return set_selection(m_selection,C,BE,P,RP);
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::set_selection(
|
||||
const Eigen::VectorXi & S,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const Eigen::VectorXi & P,
|
||||
const Eigen::VectorXi & RP)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
vector<Quaterniond,aligned_allocator<Quaterniond> > & vQ =
|
||||
m_fk_rotations_at_selection;
|
||||
vector<Vector3d> & vT = m_fk_translations_at_selection;
|
||||
forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
|
||||
m_parent_rotations_at_selection.resize(
|
||||
m_rotations.size(),Quaterniond::Identity());
|
||||
for(size_t r = 0;r<vQ.size();r++)
|
||||
{
|
||||
if(P(r)>=0)
|
||||
{
|
||||
m_parent_rotations_at_selection[r] = vQ[P(r)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(&m_selection != &S)
|
||||
{
|
||||
m_selection = S;
|
||||
}
|
||||
assert(m_selection.rows() == BE.rows());
|
||||
assert(BE.rows() == P.rows());
|
||||
assert(BE.rows() == RP.rows());
|
||||
// Zero-out S up a path of ones from e
|
||||
auto propagate = [&](const int e, const VectorXb & S, VectorXb & N)
|
||||
{
|
||||
if(S(e))
|
||||
{
|
||||
int f = e;
|
||||
while(true)
|
||||
{
|
||||
int p = P(f);
|
||||
if(p==-1||!S(p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
N(f) = false;
|
||||
f = p;
|
||||
}
|
||||
}
|
||||
};
|
||||
VectorXb prev_selection = m_selection;
|
||||
// Combine upward, group rigid parts, repeat
|
||||
while(true)
|
||||
{
|
||||
// Spread selection across rigid pieces
|
||||
VectorXb SRP(VectorXb::Zero(RP.maxCoeff()+1));
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
SRP(RP(e)) |= m_selection(e);
|
||||
}
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
m_selection(e) = SRP(RP(e));
|
||||
}
|
||||
// Clear selections below m_selection ancestors
|
||||
VectorXb new_selection = m_selection;
|
||||
for(int e = 0;e<P.rows();e++)
|
||||
{
|
||||
propagate(e,m_selection,new_selection);
|
||||
}
|
||||
m_selection = new_selection;
|
||||
if(m_selection==prev_selection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev_selection = m_selection;
|
||||
}
|
||||
|
||||
// Now selection should contain just bone roots of m_selection subtrees
|
||||
if(m_selection.array().any())
|
||||
{
|
||||
// Taking average
|
||||
Vector3d avg_pos(0,0,0);
|
||||
//m_trans_widget_trans_at_selection.setConstant(0);
|
||||
m_widget_rot_at_selection.coeffs().setConstant(0);
|
||||
m_widget.rot.coeffs().array().setConstant(0);
|
||||
Quaterniond cur_rot(0,0,0,0);
|
||||
int num_selection = 0;
|
||||
// Compute average widget for selection
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
if(m_selection(e))
|
||||
{
|
||||
Vector3d s = C.row(BE(e,0));
|
||||
Vector3d d = C.row(BE(e,1));
|
||||
auto b = (d-s).transpose().eval();
|
||||
{
|
||||
Affine3d a = Affine3d::Identity();
|
||||
a.translate(vT[e]);
|
||||
a.rotate(vQ[e]);
|
||||
avg_pos += a*s;
|
||||
}
|
||||
// Rotation of x axis to this bone
|
||||
Quaterniond rot_at_bind;
|
||||
rot_at_bind.setFromTwoVectors(Vector3d(1,0,0),b);
|
||||
const Quaterniond abs_rot = vQ[e] * rot_at_bind;
|
||||
m_widget_rot_at_selection.coeffs() += abs_rot.coeffs();
|
||||
//m_trans_widget_trans_at_selection += vT[e];
|
||||
num_selection++;
|
||||
}
|
||||
}
|
||||
// Take average
|
||||
avg_pos.array() /= (double)num_selection;
|
||||
//m_trans_widget_trans_at_selection.array() /= (double)num_selection;
|
||||
m_widget_rot_at_selection.coeffs().array() /= (double)num_selection;
|
||||
m_widget_rot_at_selection.normalize();
|
||||
m_widget.rot = m_widget_rot_at_selection;
|
||||
m_widget.pos = avg_pos;
|
||||
m_trans_widget.m_pos = avg_pos;
|
||||
//m_trans_widget.m_trans = m_trans_widget_trans_at_selection;
|
||||
m_trans_widget.m_trans.setConstant(0);
|
||||
}
|
||||
m_widget.m_is_enabled = true;
|
||||
m_trans_widget.m_is_enabled = true;
|
||||
for(int s = 0;s<m_selection.rows();s++)
|
||||
{
|
||||
// a root is selected then disable.
|
||||
if(!m_root_enabled && m_selection(s) && P(s) == -1)
|
||||
{
|
||||
m_widget.m_is_enabled = false;
|
||||
m_trans_widget.m_is_enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::set_size(const int n)
|
||||
{
|
||||
using namespace Eigen;
|
||||
clear_selection();
|
||||
m_rotations.clear();
|
||||
m_rotations.resize(n,Quaterniond::Identity());
|
||||
m_translations.clear();
|
||||
m_translations.resize(n,Vector3d(0,0,0));
|
||||
m_selection = VectorXb::Zero(n);
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset()
|
||||
{
|
||||
reset_rotations();
|
||||
reset_translations();
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset_selected()
|
||||
{
|
||||
reset_selected_rotations();
|
||||
reset_selected_translations();
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset_rotations()
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
fill(m_rotations.begin(),m_rotations.end(),Quaterniond::Identity());
|
||||
// cop out. just clear selection
|
||||
clear_selection();
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset_selected_rotations()
|
||||
{
|
||||
using namespace Eigen;
|
||||
for(int e = 0;e<m_selection.size();e++)
|
||||
{
|
||||
if(m_selection(e))
|
||||
{
|
||||
m_rotations[e] = Quaterniond::Identity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset_translations()
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
fill(m_translations.begin(),m_translations.end(),Vector3d(0,0,0));
|
||||
// cop out. just clear selection
|
||||
clear_selection();
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::reset_selected_translations()
|
||||
{
|
||||
using namespace Eigen;
|
||||
for(int e = 0;e<m_selection.size();e++)
|
||||
{
|
||||
if(m_selection(e))
|
||||
{
|
||||
m_translations[e] = Vector3d(0,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::set_rotations(const RotationList & vQ)
|
||||
{
|
||||
if(vQ.size() != m_rotations.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(!any_selection());
|
||||
m_rotations = vQ;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::set_translations(const TranslationList & vT)
|
||||
{
|
||||
if(vT.size() != m_translations.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(!any_selection());
|
||||
m_translations = vT;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::clear_selection()
|
||||
{
|
||||
m_selection.setConstant(false);
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::MouseController::any_selection() const
|
||||
{
|
||||
return m_selection.array().any();
|
||||
}
|
||||
|
||||
inline void igl::opengl2::MouseController::set_widget_mode(const WidgetMode & mode)
|
||||
{
|
||||
switch(m_widget_mode)
|
||||
{
|
||||
default:
|
||||
case WIDGET_MODE_TRANSLATE:
|
||||
m_widget.pos = m_trans_widget.m_pos+m_trans_widget.m_trans;
|
||||
break;
|
||||
case WIDGET_MODE_ROTATE:
|
||||
break;
|
||||
}
|
||||
m_widget_mode = mode;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,547 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_ROTATE_WIDGET_H
|
||||
#define IGL_OPENGL2_ROTATE_WIDGET_H
|
||||
#include "../material_colors.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// 3D Rotate tool widget similar to Maya's. Works best if field of view angle
|
||||
// is less than ~25.
|
||||
class RotateWidget
|
||||
{
|
||||
// If a is true then use A else use desaturated A
|
||||
static inline void glColor4fv(const bool a, const Eigen::Vector4f & A);
|
||||
public:
|
||||
inline static Eigen::Quaterniond axis_q(const int a);
|
||||
inline static Eigen::Vector3d view_direction(const int x, const int y);
|
||||
inline static Eigen::Vector3d view_direction(const Eigen::Vector3d & pos);
|
||||
Eigen::Vector3d pos;
|
||||
Eigen::Quaterniond rot,down_rot;
|
||||
Eigen::Vector2d down_xy,drag_xy,down_dir;
|
||||
Eigen::Vector3d udown,udrag;
|
||||
double outer_radius_on_screen;
|
||||
double outer_over_inner;
|
||||
bool m_is_enabled;
|
||||
enum DownType
|
||||
{
|
||||
DOWN_TYPE_X = 0,
|
||||
DOWN_TYPE_Y = 1,
|
||||
DOWN_TYPE_Z = 2,
|
||||
DOWN_TYPE_OUTLINE = 3,
|
||||
DOWN_TYPE_TRACKBALL = 4,
|
||||
DOWN_TYPE_NONE = 5,
|
||||
NUM_DOWN_TYPES = 6
|
||||
} down_type, selected_type;
|
||||
inline RotateWidget();
|
||||
// Vector from origin to mouse click "Unprojected" onto plane with depth of
|
||||
// origin and scale to so that outer radius is 1
|
||||
//
|
||||
// Inputs:
|
||||
// x mouse x position
|
||||
// y mouse y position
|
||||
// Returns vector
|
||||
inline Eigen::Vector3d unproject_onto(const int x, const int y) const;
|
||||
// Shoot ray from mouse click to sphere
|
||||
//
|
||||
// Inputs:
|
||||
// x mouse x position
|
||||
// y mouse y position
|
||||
// Outputs:
|
||||
// hit position of hit
|
||||
// Returns true only if there was a hit
|
||||
inline bool intersect(
|
||||
const int x,
|
||||
const int y,
|
||||
Eigen::Vector3d & hit) const;
|
||||
inline double unprojected_inner_radius() const;
|
||||
inline bool down(const int x, const int y);
|
||||
inline bool drag(const int x, const int y);
|
||||
inline bool up(const int x, const int y);
|
||||
inline bool is_down() const;
|
||||
inline void draw() const;
|
||||
inline void draw_guide() const;
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation
|
||||
#include "../PI.h"
|
||||
#include "../EPS.h"
|
||||
#include "../ray_sphere_intersect.h"
|
||||
#include "../mat_to_quat.h"
|
||||
#include "../trackball.h"
|
||||
#include "gl.h"
|
||||
#include "project.h"
|
||||
#include "unproject.h"
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
inline void igl::opengl2::RotateWidget::glColor4fv(
|
||||
const bool a,
|
||||
const Eigen::Vector4f & A)
|
||||
{
|
||||
if(a)
|
||||
{
|
||||
::glColor4fv(A.data());
|
||||
}else
|
||||
{
|
||||
Eigen::Vector4f B;
|
||||
const double f = 0.95; // desaturate by 95%
|
||||
const double L = 0.3*A(0) + 0.6*A(1) + 0.1*A(2);
|
||||
B.head(3) = A.head(3).array() + f*(L-A.head(3).array());
|
||||
B(3) = A(3);
|
||||
::glColor4fv(B.data());
|
||||
}
|
||||
}
|
||||
|
||||
inline Eigen::Quaterniond igl::opengl2::RotateWidget::axis_q(const int a)
|
||||
{
|
||||
assert(a<3 && a>=0);
|
||||
const Eigen::Quaterniond axes[3] = {
|
||||
Eigen::Quaterniond(Eigen::AngleAxisd(igl::PI*0.5,Eigen::Vector3d(0,1,0))),
|
||||
Eigen::Quaterniond(Eigen::AngleAxisd(igl::PI*0.5,Eigen::Vector3d(1,0,0))),
|
||||
Eigen::Quaterniond::Identity()};
|
||||
return axes[a];
|
||||
}
|
||||
|
||||
inline Eigen::Vector3d igl::opengl2::RotateWidget::view_direction(const int x, const int y)
|
||||
{
|
||||
using namespace Eigen;
|
||||
const Vector3d win_s(x,y,0), win_d(x,y,1);
|
||||
const Vector3d s = unproject(win_s);
|
||||
const Vector3d d = unproject(win_d);
|
||||
return d-s;
|
||||
}
|
||||
|
||||
inline Eigen::Vector3d igl::opengl2::RotateWidget::view_direction(const Eigen::Vector3d & pos)
|
||||
{
|
||||
using namespace Eigen;
|
||||
const Vector3d ppos = project(pos);
|
||||
return view_direction(ppos(0),ppos(1));
|
||||
}
|
||||
|
||||
inline igl::opengl2::RotateWidget::RotateWidget():
|
||||
pos(0,0,0),
|
||||
rot(Eigen::Quaterniond::Identity()),
|
||||
down_rot(rot),
|
||||
down_xy(-1,-1),drag_xy(-1,-1),
|
||||
outer_radius_on_screen(91.),
|
||||
outer_over_inner(1.13684210526),
|
||||
m_is_enabled(true),
|
||||
down_type(DOWN_TYPE_NONE),
|
||||
selected_type(DOWN_TYPE_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
inline Eigen::Vector3d igl::opengl2::RotateWidget::unproject_onto(
|
||||
const int x,
|
||||
const int y) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
// KNOWN BUG: This projects to same depths as pos. I think what we actually
|
||||
// want is The intersection with the plane perpendicular to the view
|
||||
// direction at pos. If the field of view angle is small then this difference
|
||||
// is negligible.
|
||||
//const Vector3d ppos = project(pos);
|
||||
//const Vector3d uxy = unproject( Vector3d(x,y,ppos(2)));
|
||||
// http://en.wikipedia.org/wiki/Line-plane_intersection
|
||||
//
|
||||
// Hrrmmm. There's still something wrong here if the ball's in the corner of
|
||||
// the screen. Am I somehow not accounting for perspective correctly?
|
||||
//
|
||||
// Q: What about just projecting the circle's equation and solving for the
|
||||
// distance?
|
||||
const Vector3d l0 = unproject(Vector3d(x,y,0));
|
||||
const Vector3d l = unproject(Vector3d(x,y,1))-l0;
|
||||
const Vector3d n = view_direction(pos);
|
||||
const double t = (pos-l0).dot(n)/l.dot(n);
|
||||
const Vector3d uxy = l0+t*l;
|
||||
return (uxy-pos)/unprojected_inner_radius()*outer_over_inner*outer_over_inner;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::RotateWidget::intersect(
|
||||
const int x,
|
||||
const int y,
|
||||
Eigen::Vector3d & hit) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
Vector3d view = view_direction(x,y);
|
||||
const Vector3d ppos = project(pos);
|
||||
Vector3d uxy = unproject(Vector3d(x,y,ppos(2)));
|
||||
double t0,t1;
|
||||
if(!ray_sphere_intersect(uxy,view,pos,unprojected_inner_radius(),t0,t1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
hit = uxy+t0*view;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline double igl::opengl2::RotateWidget::unprojected_inner_radius() const
|
||||
{
|
||||
using namespace Eigen;
|
||||
Vector3d off,ppos,ppos_off,pos_off;
|
||||
project(pos,ppos);
|
||||
ppos_off = ppos;
|
||||
ppos_off(0) += outer_radius_on_screen/outer_over_inner;
|
||||
unproject(ppos_off,pos_off);
|
||||
return (pos-pos_off).norm();
|
||||
}
|
||||
inline bool igl::opengl2::RotateWidget::down(const int x, const int y)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
if(!m_is_enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
down_type = DOWN_TYPE_NONE;
|
||||
selected_type = DOWN_TYPE_NONE;
|
||||
down_xy = Vector2d(x,y);
|
||||
drag_xy = down_xy;
|
||||
down_rot = rot;
|
||||
Vector3d ppos = project(pos);
|
||||
const double r = (ppos.head(2) - down_xy).norm();
|
||||
const double thresh = 3;
|
||||
if(fabs(r - outer_radius_on_screen)<thresh)
|
||||
{
|
||||
udown = unproject_onto(x,y);
|
||||
udrag = udown;
|
||||
down_type = DOWN_TYPE_OUTLINE;
|
||||
selected_type = DOWN_TYPE_OUTLINE;
|
||||
// project mouse to same depth as pos
|
||||
return true;
|
||||
}else if(r < outer_radius_on_screen/outer_over_inner+thresh*0.5)
|
||||
{
|
||||
Vector3d hit;
|
||||
const bool is_hit = intersect(down_xy(0),down_xy(1),hit);
|
||||
if(!is_hit)
|
||||
{
|
||||
//cout<<"~~~!is_hit"<<endl;
|
||||
}
|
||||
auto on_meridian = [&](
|
||||
const Vector3d & hit,
|
||||
const Quaterniond & rot,
|
||||
const Quaterniond & m,
|
||||
Vector3d & pl_hit) -> bool
|
||||
{
|
||||
// project onto rotate plane
|
||||
pl_hit = hit-pos;
|
||||
pl_hit = (m.conjugate()*rot.conjugate()*pl_hit).eval();
|
||||
pl_hit(2) = 0;
|
||||
pl_hit = (rot*m*pl_hit).eval();
|
||||
pl_hit.normalize();
|
||||
pl_hit *= unprojected_inner_radius();
|
||||
pl_hit += pos;
|
||||
return (project(pl_hit).head(2)-project(hit).head(2)).norm()<2*thresh;
|
||||
};
|
||||
udown = (hit-pos).normalized()/outer_radius_on_screen;
|
||||
udrag = udown;
|
||||
for(int a = 0;a<3;a++)
|
||||
{
|
||||
Vector3d pl_hit;
|
||||
if(on_meridian(hit,rot,Quaterniond(axis_q(a)),pl_hit))
|
||||
{
|
||||
udown = (pl_hit-pos).normalized()/outer_radius_on_screen;
|
||||
udrag = udown;
|
||||
down_type = DownType(DOWN_TYPE_X+a);
|
||||
selected_type = down_type;
|
||||
{
|
||||
Vector3d dir3 = axis_q(a).conjugate()*down_rot.conjugate()*(hit-pos);
|
||||
dir3 = AngleAxisd(-PI*0.5,Vector3d(0,0,1))*dir3;
|
||||
dir3 = (rot*axis_q(a)*dir3).eval();
|
||||
down_dir = (project((hit+dir3).eval())-project(hit)).head(2);
|
||||
down_dir.normalize();
|
||||
//// flip y because y coordinate is going to be given backwards in
|
||||
//// drag()
|
||||
//down_dir(1) *= -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//assert(is_hit);
|
||||
down_type = DOWN_TYPE_TRACKBALL;
|
||||
selected_type = DOWN_TYPE_TRACKBALL;
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::RotateWidget::drag(const int x, const int y)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
if(!m_is_enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
drag_xy = Vector2d(x,y);
|
||||
switch(down_type)
|
||||
{
|
||||
case DOWN_TYPE_NONE:
|
||||
return false;
|
||||
default:
|
||||
{
|
||||
const Quaterniond & q = axis_q(down_type-DOWN_TYPE_X);
|
||||
const double dtheta = -(drag_xy - down_xy).dot(down_dir)/
|
||||
outer_radius_on_screen/outer_over_inner*PI/2.;
|
||||
Quaterniond dq(AngleAxisd(dtheta,down_rot*q*Vector3d(0,0,1)));
|
||||
rot = dq * down_rot;
|
||||
udrag = dq * udown;
|
||||
return true;
|
||||
}
|
||||
case DOWN_TYPE_OUTLINE:
|
||||
{
|
||||
Vector3d ppos = project(pos);
|
||||
// project mouse to same depth as pos
|
||||
udrag = unproject_onto(x,y);
|
||||
const Vector2d A = down_xy - ppos.head(2);
|
||||
const Vector2d B = drag_xy - ppos.head(2);
|
||||
const double dtheta = atan2(A(0)*B(1)-A(1)*B(0),A(0)*B(0)+A(1)*B(1));
|
||||
Vector3d n = view_direction(pos).normalized();
|
||||
Quaterniond dq(AngleAxisd(dtheta,-n));
|
||||
//Vector3d n = udrag.cross(udown).normalized();
|
||||
//Quaterniond dq(AngleAxisd(fabs(dtheta),-n));
|
||||
rot = dq * down_rot;
|
||||
}
|
||||
return true;
|
||||
case DOWN_TYPE_TRACKBALL:
|
||||
{
|
||||
Vector3d ppos = project(pos);
|
||||
const double r = (double)outer_radius_on_screen/outer_over_inner*2.0;
|
||||
//const int h = w;
|
||||
Vector4i vp;
|
||||
glGetIntegerv(GL_VIEWPORT,vp.data());
|
||||
const int h = vp(3);
|
||||
Quaterniond dq;
|
||||
trackball(
|
||||
r,r,
|
||||
1,
|
||||
Quaterniond::Identity(),
|
||||
double( down_xy(0)-ppos(0) )+r/2.,
|
||||
double((h-down_xy(1))-(h-ppos(1)))+r/2.,
|
||||
double( x-ppos(0) )+r/2.,
|
||||
double( (h-y)-(h-ppos(1)))+r/2.,
|
||||
dq);
|
||||
// We've computed change in rotation according to this view:
|
||||
// R = mv * r, R' = rot * (mv * r)
|
||||
// But we only want new value for r:
|
||||
// R' = mv * r'
|
||||
// mv * r' = rot * (mv * r)
|
||||
// r' = mv* * rot * mv * r
|
||||
Matrix4d mv;
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX,mv.data());
|
||||
Quaterniond scene_rot;
|
||||
// Convert modelview matrix to quaternion
|
||||
mat4_to_quat(mv.data(),scene_rot.coeffs().data());
|
||||
scene_rot.normalize();
|
||||
rot = scene_rot.conjugate() * dq * scene_rot * down_rot;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::RotateWidget::up(const int /*x*/, const int /*y*/)
|
||||
{
|
||||
// even if disabled process up
|
||||
down_type = DOWN_TYPE_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::RotateWidget::is_down() const
|
||||
{
|
||||
return down_type != DOWN_TYPE_NONE;
|
||||
}
|
||||
|
||||
inline void igl::opengl2::RotateWidget::draw() const
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT | GL_LINE_BIT);
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glLineWidth(2.0);
|
||||
|
||||
double r = unprojected_inner_radius();
|
||||
Vector3d view = view_direction(pos).normalized();
|
||||
|
||||
auto draw_circle = [&](const bool cull)
|
||||
{
|
||||
Vector3d view = view_direction(pos).normalized();
|
||||
glBegin(GL_LINES);
|
||||
const double th_step = (2.0*igl::PI/100.0);
|
||||
for(double th = 0;th<2.0*igl::PI+th_step;th+=th_step)
|
||||
{
|
||||
Vector3d a(cos(th),sin(th),0.0);
|
||||
Vector3d b(cos(th+th_step),sin(th+th_step),0.0);
|
||||
if(!cull || (0.5*(a+b)).dot(view)<FLOAT_EPS)
|
||||
{
|
||||
glVertex3dv(a.data());
|
||||
glVertex3dv(b.data());
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
};
|
||||
|
||||
|
||||
glPushMatrix();
|
||||
glTranslated(pos(0),pos(1),pos(2));
|
||||
|
||||
glScaled(r,r,r);
|
||||
// Draw outlines
|
||||
{
|
||||
glPushMatrix();
|
||||
glColor4fv(m_is_enabled,MAYA_GREY);
|
||||
Quaterniond q;
|
||||
q.setFromTwoVectors(Vector3d(0,0,1),view);
|
||||
glMultMatrixd(Affine3d(q).matrix().data());
|
||||
draw_circle(false);
|
||||
glScaled(outer_over_inner,outer_over_inner,outer_over_inner);
|
||||
if(selected_type == DOWN_TYPE_OUTLINE)
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_YELLOW);
|
||||
}else
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_CYAN);
|
||||
}
|
||||
draw_circle(false);
|
||||
glPopMatrix();
|
||||
}
|
||||
// Draw quartiles
|
||||
{
|
||||
glPushMatrix();
|
||||
glMultMatrixd(Affine3d(rot).matrix().data());
|
||||
if(selected_type == DOWN_TYPE_Z)
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_YELLOW);
|
||||
}else
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_BLUE);
|
||||
}
|
||||
draw_circle(true);
|
||||
if(selected_type == DOWN_TYPE_Y)
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_YELLOW);
|
||||
}else
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_GREEN);
|
||||
}
|
||||
glRotated(90.0,1.0,0.0,0.0);
|
||||
draw_circle(true);
|
||||
if(selected_type == DOWN_TYPE_X)
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_YELLOW);
|
||||
}else
|
||||
{
|
||||
glColor4fv(m_is_enabled,MAYA_RED);
|
||||
}
|
||||
glRotated(90.0,0.0,1.0,0.0);
|
||||
draw_circle(true);
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4fv(m_is_enabled,MAYA_GREY);
|
||||
draw_guide();
|
||||
glPopMatrix();
|
||||
|
||||
glPopAttrib();
|
||||
};
|
||||
|
||||
inline void igl::opengl2::RotateWidget::draw_guide() const
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
glPushAttrib(
|
||||
GL_DEPTH_BUFFER_BIT |
|
||||
GL_ENABLE_BIT |
|
||||
GL_POLYGON_BIT |
|
||||
GL_POINT_BIT |
|
||||
GL_TRANSFORM_BIT |
|
||||
GL_STENCIL_BUFFER_BIT |
|
||||
GL_LIGHTING_BIT);
|
||||
|
||||
// http://www.codeproject.com/Articles/23444/A-Simple-OpenGL-Stipple-Polygon-Example-EP_OpenGL_
|
||||
const GLubyte halftone[] = {
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
|
||||
|
||||
|
||||
switch(down_type)
|
||||
{
|
||||
case DOWN_TYPE_NONE:
|
||||
case DOWN_TYPE_TRACKBALL:
|
||||
goto finish;
|
||||
case DOWN_TYPE_OUTLINE:
|
||||
glScaled(outer_over_inner,outer_over_inner,outer_over_inner);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
{
|
||||
const Vector3d nudown(udown.normalized()),
|
||||
nudrag(udrag.normalized());
|
||||
glPushMatrix();
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
glPointSize(5.);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3dv(nudown.data());
|
||||
glVertex3d(0,0,0);
|
||||
glVertex3dv(nudrag.data());
|
||||
glEnd();
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3dv(nudown.data());
|
||||
glVertex3d(0,0,0);
|
||||
glVertex3dv(nudrag.data());
|
||||
glEnd();
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glPolygonStipple(halftone);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex3d(0,0,0);
|
||||
Quaterniond dq = rot * down_rot.conjugate();
|
||||
//dq.setFromTwoVectors(nudown,nudrag);
|
||||
for(double t = 0;t<1;t+=0.1)
|
||||
{
|
||||
const Vector3d p = Quaterniond::Identity().slerp(t,dq) * nudown;
|
||||
glVertex3dv(p.data());
|
||||
}
|
||||
glVertex3dv(nudrag.data());
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
finish:
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,211 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_TRANSLATE_WIDGET_H
|
||||
#define IGL_OPENGL2_TRANSLATE_WIDGET_H
|
||||
#include "../material_colors.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
class TranslateWidget
|
||||
{
|
||||
public:
|
||||
// m_pos position of center
|
||||
// m_trans translation vector
|
||||
// m_down_xy mouse position on down
|
||||
// m_drag_xy mouse position on drag
|
||||
// m_is_enabled whether enabled
|
||||
Eigen::Vector3d m_pos,m_trans,m_down_trans;
|
||||
Eigen::Vector2d m_down_xy, m_drag_xy;
|
||||
bool m_is_enabled;
|
||||
double m_len;
|
||||
enum DownType
|
||||
{
|
||||
DOWN_TYPE_X = 0,
|
||||
DOWN_TYPE_Y = 1,
|
||||
DOWN_TYPE_Z = 2,
|
||||
DOWN_TYPE_CENTER = 3,
|
||||
DOWN_TYPE_NONE = 4,
|
||||
NUM_DOWN_TYPES = 5
|
||||
} m_down_type, m_selected_type;
|
||||
inline TranslateWidget(const Eigen::Vector3d & pos = Eigen::Vector3d(0,0,0));
|
||||
inline bool down(const int x, const int y);
|
||||
inline bool drag(const int x, const int y);
|
||||
inline bool up(const int x, const int y);
|
||||
inline bool is_down() const;
|
||||
inline void draw() const;
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation
|
||||
#include "project.h"
|
||||
#include "unproject.h"
|
||||
|
||||
inline igl::opengl2::TranslateWidget::TranslateWidget(
|
||||
const Eigen::Vector3d & pos):
|
||||
m_pos(pos),
|
||||
m_trans(0,0,0),
|
||||
m_down_xy(-1,-1),
|
||||
m_drag_xy(-1,-1),
|
||||
m_is_enabled(true),
|
||||
m_len(50),
|
||||
m_down_type(DOWN_TYPE_NONE),
|
||||
m_selected_type(DOWN_TYPE_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::TranslateWidget::down(const int x, const int y)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
if(!m_is_enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_down_trans = m_trans;
|
||||
m_down_xy = Vector2d(x,y);
|
||||
m_drag_xy = m_down_xy;
|
||||
m_down_type = DOWN_TYPE_NONE;
|
||||
m_selected_type = DOWN_TYPE_NONE;
|
||||
Vector3d ppos = project((m_pos+m_trans).eval());
|
||||
const double r = (ppos.head(2) - m_down_xy).norm();
|
||||
const double center_thresh = 10;
|
||||
if(r < center_thresh)
|
||||
{
|
||||
m_down_type = DOWN_TYPE_CENTER;
|
||||
m_selected_type = m_down_type;
|
||||
return true;
|
||||
}else if(r < m_len)
|
||||
{
|
||||
// Might be hit on lines
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::TranslateWidget::drag(const int x, const int y)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
if(!m_is_enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_drag_xy = Vector2d(x,y);
|
||||
switch(m_down_type)
|
||||
{
|
||||
case DOWN_TYPE_NONE:
|
||||
return false;
|
||||
default:
|
||||
{
|
||||
Vector3d ppos = project((m_pos+m_trans).eval());
|
||||
Vector3d drag3(m_drag_xy(0),m_drag_xy(1),ppos(2));
|
||||
Vector3d down3(m_down_xy(0),m_down_xy(1),ppos(2));
|
||||
m_trans = m_down_trans + unproject(drag3)-unproject(down3);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::TranslateWidget::up(const int /*x*/, const int /*y*/)
|
||||
{
|
||||
// even if disabled process up
|
||||
m_down_type = DOWN_TYPE_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool igl::opengl2::TranslateWidget::is_down() const
|
||||
{
|
||||
return m_down_type != DOWN_TYPE_NONE;
|
||||
}
|
||||
|
||||
inline void igl::opengl2::TranslateWidget::draw() const
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT | GL_LINE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glLineWidth(2.0);
|
||||
auto draw_axes = [&]()
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1,0,0);
|
||||
glVertex3f(0,0,0);
|
||||
glVertex3f(1,0,0);
|
||||
glColor3f(0,1,0);
|
||||
glVertex3f(0,0,0);
|
||||
glVertex3f(0,1,0);
|
||||
glColor3f(0,0,1);
|
||||
glVertex3f(0,0,0);
|
||||
glVertex3f(0,0,1);
|
||||
glEnd();
|
||||
};
|
||||
auto draw_cube = []
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||
glEnd();
|
||||
};
|
||||
glPushMatrix();
|
||||
glTranslated( m_pos(0)+m_trans(0), m_pos(1)+m_trans(1), m_pos(2)+m_trans(2));
|
||||
|
||||
{
|
||||
Vector3d off,ppos,ppos_off,pos_off;
|
||||
project((m_pos+m_trans).eval(),ppos);
|
||||
ppos_off = ppos;
|
||||
ppos_off(0) += m_len;
|
||||
unproject(ppos_off,pos_off);
|
||||
const double r = (m_pos+m_trans-pos_off).norm();
|
||||
glScaled(r,r,r);
|
||||
}
|
||||
|
||||
draw_axes();
|
||||
glScaled(0.05,0.05,0.05);
|
||||
if(m_selected_type == DOWN_TYPE_CENTER)
|
||||
{
|
||||
glColor3fv(MAYA_YELLOW.data());
|
||||
}else
|
||||
{
|
||||
glColor3fv(MAYA_GREY.data());
|
||||
}
|
||||
draw_cube();
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,283 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "draw_beach_ball.h"
|
||||
#include "gl.h"
|
||||
|
||||
// I'm not sure why windows would need it this way:
|
||||
// http://lists.cairographics.org/archives/cairo/2008-January/012722.html
|
||||
#ifdef _MSC_VER
|
||||
#define SAFE_INLINE __inline
|
||||
#else
|
||||
#define SAFE_INLINE inline
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
// Most of this implementation comes from the AntTweakBar source code:
|
||||
// TwMgr.cpp, TwMgr.h, TwColor.h, TwColor.cpp, TwOpenGL.h and TwOpenGL.cpp
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Begin Copied Straight from AntTweakBar
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
enum EArrowParts { ARROW_CONE, ARROW_CONE_CAP, ARROW_CYL, ARROW_CYL_CAP };
|
||||
|
||||
template <typename T> SAFE_INLINE const T& TClamp(const T& X, const T& Limit1, const T& Limit2)
|
||||
{
|
||||
if( Limit1<Limit2 )
|
||||
return (X<=Limit1) ? Limit1 : ( (X>=Limit2) ? Limit2 : X );
|
||||
else
|
||||
return (X<=Limit2) ? Limit2 : ( (X>=Limit1) ? Limit1 : X );
|
||||
}
|
||||
|
||||
typedef unsigned int color32;
|
||||
static SAFE_INLINE color32 Color32FromARGBi(int A, int R, int G, int B)
|
||||
{
|
||||
return (((color32)TClamp(A, 0, 255))<<24) | (((color32)TClamp(R, 0, 255))<<16) | (((color32)TClamp(G, 0, 255))<<8) | ((color32)TClamp(B, 0, 255));
|
||||
}
|
||||
|
||||
static SAFE_INLINE color32 Color32FromARGBf(float A, float R, float G, float B)
|
||||
{
|
||||
return (((color32)TClamp(A*256.0f, 0.0f, 255.0f))<<24) | (((color32)TClamp(R*256.0f, 0.0f, 255.0f))<<16) | (((color32)TClamp(G*256.0f, 0.0f, 255.0f))<<8) | ((color32)TClamp(B*256.0f, 0.0f, 255.0f));
|
||||
}
|
||||
|
||||
static SAFE_INLINE void Color32ToARGBi(color32 Color, int *A, int *R, int *G, int *B)
|
||||
{
|
||||
if(A) *A = (Color>>24)&0xff;
|
||||
if(R) *R = (Color>>16)&0xff;
|
||||
if(G) *G = (Color>>8)&0xff;
|
||||
if(B) *B = Color&0xff;
|
||||
}
|
||||
|
||||
static SAFE_INLINE void Color32ToARGBf(color32 Color, float *A, float *R, float *G, float *B)
|
||||
{
|
||||
if(A) *A = (1.0f/255.0f)*float((Color>>24)&0xff);
|
||||
if(R) *R = (1.0f/255.0f)*float((Color>>16)&0xff);
|
||||
if(G) *G = (1.0f/255.0f)*float((Color>>8)&0xff);
|
||||
if(B) *B = (1.0f/255.0f)*float(Color&0xff);
|
||||
}
|
||||
|
||||
static color32 ColorBlend(color32 Color1, color32 Color2, float S)
|
||||
{
|
||||
float a1, r1, g1, b1, a2, r2, g2, b2;
|
||||
Color32ToARGBf(Color1, &a1, &r1, &g1, &b1);
|
||||
Color32ToARGBf(Color2, &a2, &r2, &g2, &b2);
|
||||
float t = 1.0f-S;
|
||||
return Color32FromARGBf(t*a1+S*a2, t*r1+S*r2, t*g1+S*g2, t*b1+S*b2);
|
||||
}
|
||||
|
||||
static std::vector<float> s_SphTri;
|
||||
static std::vector<color32> s_SphCol;
|
||||
static void CreateSphere()
|
||||
{
|
||||
const int SUBDIV = 7;
|
||||
s_SphTri.clear();
|
||||
s_SphCol.clear();
|
||||
|
||||
const float A[8*3] = { 1,0,0, 0,0,-1, -1,0,0, 0,0,1, 0,0,1, 1,0,0, 0,0,-1, -1,0,0 };
|
||||
const float B[8*3] = { 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0 };
|
||||
const float C[8*3] = { 0,0,1, 1,0,0, 0,0,-1, -1,0,0, 1,0,0, 0,0,-1, -1,0,0, 0,0,1 };
|
||||
//const color32 COL_A[8] = { 0xffff8080, 0xff000080, 0xff800000, 0xff8080ff, 0xff8080ff, 0xffff8080, 0xff000080, 0xff800000 };
|
||||
//const color32 COL_B[8] = { 0xff80ff80, 0xff80ff80, 0xff80ff80, 0xff80ff80, 0xff008000, 0xff008000, 0xff008000, 0xff008000 };
|
||||
//const color32 COL_C[8] = { 0xff8080ff, 0xffff8080, 0xff000080, 0xff800000, 0xffff8080, 0xff000080, 0xff800000, 0xff8080ff };
|
||||
const color32 COL_A[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
|
||||
const color32 COL_B[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
|
||||
const color32 COL_C[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
|
||||
|
||||
int i, j, k, l;
|
||||
float xa, ya, za, xb, yb, zb, xc, yc, zc, x, y, z, norm, u[3], v[3];
|
||||
color32 col;
|
||||
for( i=0; i<8; ++i )
|
||||
{
|
||||
xa = A[3*i+0]; ya = A[3*i+1]; za = A[3*i+2];
|
||||
xb = B[3*i+0]; yb = B[3*i+1]; zb = B[3*i+2];
|
||||
xc = C[3*i+0]; yc = C[3*i+1]; zc = C[3*i+2];
|
||||
for( j=0; j<=SUBDIV; ++j )
|
||||
for( k=0; k<=2*(SUBDIV-j); ++k )
|
||||
{
|
||||
if( k%2==0 )
|
||||
{
|
||||
u[0] = ((float)j)/(SUBDIV+1);
|
||||
v[0] = ((float)(k/2))/(SUBDIV+1);
|
||||
u[1] = ((float)(j+1))/(SUBDIV+1);
|
||||
v[1] = ((float)(k/2))/(SUBDIV+1);
|
||||
u[2] = ((float)j)/(SUBDIV+1);
|
||||
v[2] = ((float)(k/2+1))/(SUBDIV+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
u[0] = ((float)j)/(SUBDIV+1);
|
||||
v[0] = ((float)(k/2+1))/(SUBDIV+1);
|
||||
u[1] = ((float)(j+1))/(SUBDIV+1);
|
||||
v[1] = ((float)(k/2))/(SUBDIV+1);
|
||||
u[2] = ((float)(j+1))/(SUBDIV+1);
|
||||
v[2] = ((float)(k/2+1))/(SUBDIV+1);
|
||||
}
|
||||
|
||||
for( l=0; l<3; ++l )
|
||||
{
|
||||
x = (1.0f-u[l]-v[l])*xa + u[l]*xb + v[l]*xc;
|
||||
y = (1.0f-u[l]-v[l])*ya + u[l]*yb + v[l]*yc;
|
||||
z = (1.0f-u[l]-v[l])*za + u[l]*zb + v[l]*zc;
|
||||
norm = sqrtf(x*x+y*y+z*z);
|
||||
x /= norm; y /= norm; z /= norm;
|
||||
s_SphTri.push_back(x); s_SphTri.push_back(y); s_SphTri.push_back(z);
|
||||
static const float FLOAT_EPS = 1.0e-7f;
|
||||
if( u[l]+v[l]>FLOAT_EPS )
|
||||
col = ColorBlend(COL_A[i], ColorBlend(COL_B[i], COL_C[i], v[l]/(u[l]+v[l])), u[l]+v[l]);
|
||||
else
|
||||
col = COL_A[i];
|
||||
//if( (j==0 && k==0) || (j==0 && k==2*SUBDIV) || (j==SUBDIV && k==0) )
|
||||
// col = 0xffff0000;
|
||||
s_SphCol.push_back(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
//s_SphTriProj.clear();
|
||||
//s_SphTriProj.resize(2*s_SphCol.size(), 0);
|
||||
//s_SphColLight.clear();
|
||||
//s_SphColLight.resize(s_SphCol.size(), 0);
|
||||
}
|
||||
|
||||
static std::vector<float> s_ArrowTri[4];
|
||||
static std::vector<float> s_ArrowNorm[4];
|
||||
static void CreateArrow()
|
||||
{
|
||||
const int SUBDIV = 15;
|
||||
const float CYL_RADIUS = 0.08f;
|
||||
const float CONE_RADIUS = 0.16f;
|
||||
const float CONE_LENGTH = 0.25f;
|
||||
const float ARROW_BGN = -1.1f;
|
||||
const float ARROW_END = 1.15f;
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
{
|
||||
s_ArrowTri[i].clear();
|
||||
s_ArrowNorm[i].clear();
|
||||
}
|
||||
|
||||
float x0, x1, y0, y1, z0, z1, a0, a1, nx, nn;
|
||||
for(i=0; i<SUBDIV; ++i)
|
||||
{
|
||||
static const float FLOAT_PI = 3.14159265358979323846f;
|
||||
a0 = 2.0f*FLOAT_PI*(float(i))/SUBDIV;
|
||||
a1 = 2.0f*FLOAT_PI*(float(i+1))/SUBDIV;
|
||||
x0 = ARROW_BGN;
|
||||
x1 = ARROW_END-CONE_LENGTH;
|
||||
y0 = cosf(a0);
|
||||
z0 = sinf(a0);
|
||||
y1 = cosf(a1);
|
||||
z1 = sinf(a1);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
|
||||
s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(0); s_ArrowTri[ARROW_CYL_CAP].push_back(0);
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*z0);
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
|
||||
x0 = ARROW_END-CONE_LENGTH;
|
||||
x1 = ARROW_END;
|
||||
nx = CONE_RADIUS/(x1-x0);
|
||||
nn = 1.0f/sqrtf(nx*nx+1);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z0);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
|
||||
s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(0); s_ArrowTri[ARROW_CONE_CAP].push_back(0);
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*z1);
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*y0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*z0);
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
|
||||
}
|
||||
|
||||
//for(i=0; i<4; ++i)
|
||||
//{
|
||||
// s_ArrowTriProj[i].clear();
|
||||
// s_ArrowTriProj[i].resize(2*(s_ArrowTri[i].size()/3), 0);
|
||||
// s_ArrowColLight[i].clear();
|
||||
// s_ArrowColLight[i].resize(s_ArrowTri[i].size()/3, 0);
|
||||
//}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// End Copied Straight from AntTweakBar
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_beach_ball()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
CreateSphere();
|
||||
// Keep track of opengl settings
|
||||
int cm;
|
||||
glGetIntegerv(GL_COLOR_MATERIAL,&cm);
|
||||
// Draw triangles
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
|
||||
float mat_ambient[4] = {0.1,0.1,0.1,1.0};
|
||||
float mat_specular[4] = {0.0,0.0,0.0,1.0};
|
||||
float mat_shininess = 1;
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
|
||||
|
||||
glPushMatrix();
|
||||
glScalef(0.7,0.7,0.7);
|
||||
glEnable(GL_NORMALIZE);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(int i = 0;i<(int)s_SphCol.size();i++)
|
||||
{
|
||||
glNormal3fv(&s_SphTri[i*3]);
|
||||
glColor4ub(GLubyte(s_SphCol[i]>>16), GLubyte(s_SphCol[i]>>8), GLubyte(s_SphCol[i]), GLubyte(s_SphCol[i]>>24));
|
||||
glVertex3fv(&s_SphTri[i*3]);
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
CreateArrow();
|
||||
for(int k = 0;k<3;k++)
|
||||
{
|
||||
glPushMatrix();
|
||||
glColor3f(k==0,k==1,k==2);
|
||||
glRotatef((k==2?-1.0:1.0)*90,k==0,k==2,k==1);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(int j = 0;j<4;j++)
|
||||
{
|
||||
for(int i = 0;i<(int)s_ArrowTri[j].size();i+=3)
|
||||
{
|
||||
glNormal3fv(&s_ArrowNorm[j][i]);
|
||||
glVertex3fv(&s_ArrowTri[j][i]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
(cm ? glEnable(GL_COLOR_MATERIAL):glDisable(GL_COLOR_MATERIAL));
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_BEACH_BALL_H
|
||||
#define IGL_OPENGL2_DRAW_BEACH_BALL_H
|
||||
#include "../igl_inline.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Draw a beach ball icon/glyph (from AntTweakBar) at the current origin
|
||||
// according to the current orientation: ball has radius 0.75 and axis have
|
||||
// length 1.15
|
||||
IGL_INLINE void draw_beach_ball();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_beach_ball.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,161 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "draw_floor.h"
|
||||
#include "gl.h"
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_floor(const float * colorA, const float * colorB,
|
||||
const int GridSizeX,
|
||||
const int GridSizeY)
|
||||
{
|
||||
const float SizeX = 0.5f*100./(double)GridSizeX;
|
||||
const float SizeY = 0.5f*100./(double)GridSizeY;
|
||||
// old settings
|
||||
int old_lighting=0,old_color_material=0;
|
||||
glGetIntegerv(GL_LIGHTING,&old_lighting);
|
||||
glGetIntegerv(GL_COLOR_MATERIAL,&old_color_material);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColorMaterial( GL_FRONT, GL_EMISSION);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||
// Set material
|
||||
const float black[] = {0.,0.,0.,1.};
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, black);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, black);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, black);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS,0);
|
||||
const bool use_lighting = false;
|
||||
if(use_lighting)
|
||||
{
|
||||
glEnable(GL_LIGHTING);
|
||||
}else
|
||||
{
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3f(0,1,0);
|
||||
for (int x =-GridSizeX/2;x<GridSizeX/2;++x)
|
||||
{
|
||||
for (int y =-GridSizeY/2;y<GridSizeY/2;++y)
|
||||
{
|
||||
if ((x+y)&0x00000001) //modulo 2
|
||||
{
|
||||
glColor4fv(colorA);
|
||||
}else
|
||||
{
|
||||
glColor4fv(colorB);
|
||||
}
|
||||
glVertex3f( x*SizeX,0,(y+1)*SizeY);
|
||||
glVertex3f((x+1)*SizeX,0,(y+1)*SizeY);
|
||||
glVertex3f((x+1)*SizeX,0, y*SizeY);
|
||||
glVertex3f( x*SizeX,0, y*SizeY);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
(old_lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING));
|
||||
(old_color_material? glEnable(GL_COLOR_MATERIAL) : glDisable(GL_COLOR_MATERIAL));
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_floor()
|
||||
{
|
||||
const float grey[] = {0.80,0.80,0.80,1.};
|
||||
const float white[] = {0.95,0.95,0.95,1.};
|
||||
igl::opengl2::draw_floor(grey,white);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_floor_outline(const float * colorA, const float * colorB,
|
||||
const int GridSizeX,
|
||||
const int GridSizeY)
|
||||
{
|
||||
const float SizeX = 0.5f*100./(double)GridSizeX;
|
||||
const float SizeY = 0.5f*100./(double)GridSizeY;
|
||||
float old_line_width =0;
|
||||
// old settings
|
||||
int old_lighting=0,old_color_material=0;
|
||||
glGetIntegerv(GL_LIGHTING,&old_lighting);
|
||||
glGetIntegerv(GL_COLOR_MATERIAL,&old_color_material);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// Set material
|
||||
const float black[] = {0.,0.,0.,1.};
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, black);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, black);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, black);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS,0);
|
||||
const bool use_lighting = false;
|
||||
if(use_lighting)
|
||||
{
|
||||
glEnable(GL_LIGHTING);
|
||||
}else
|
||||
{
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
glLineWidth(2.0f);
|
||||
glBegin(GL_LINES);
|
||||
for (int x =-GridSizeX/2;x<=GridSizeX/2;++x)
|
||||
{
|
||||
if(x!=(GridSizeX/2))
|
||||
{
|
||||
for(int s = -1;s<2;s+=2)
|
||||
{
|
||||
int y = s*(GridSizeY/2);
|
||||
int cy = y==(GridSizeY/2) ? y-1 : y;
|
||||
if ((x+cy)&0x00000001) //modulo 2
|
||||
{
|
||||
glColor4fv(colorA);
|
||||
//glColor3f(1,0,0);
|
||||
}else
|
||||
{
|
||||
glColor4fv(colorB);
|
||||
//glColor3f(0,0,1);
|
||||
}
|
||||
glVertex3f((x+1)*SizeX,0,y*SizeY);
|
||||
glVertex3f( x*SizeX,0,y*SizeY);
|
||||
}
|
||||
}
|
||||
if(x==-(GridSizeX/2) || x==(GridSizeX/2))
|
||||
{
|
||||
int cx = x==(GridSizeX/2) ? x-1 : x;
|
||||
for (int y =-GridSizeY/2;y<GridSizeY/2;++y)
|
||||
{
|
||||
if ((cx+y)&0x00000001) //modulo 2
|
||||
{
|
||||
glColor4fv(colorA);
|
||||
//glColor3f(1,0,0);
|
||||
}else
|
||||
{
|
||||
glColor4fv(colorB);
|
||||
//glColor3f(0,0,1);
|
||||
}
|
||||
glVertex3f(x*SizeX,0,(y+1)*SizeY);
|
||||
glVertex3f(x*SizeX,0, y*SizeY);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glGetFloatv(GL_LINE_WIDTH,&old_line_width);
|
||||
glLineWidth(old_line_width);
|
||||
(old_lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING));
|
||||
(old_color_material? glEnable(GL_COLOR_MATERIAL) : glDisable(GL_COLOR_MATERIAL));
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_floor_outline()
|
||||
{
|
||||
const float grey[] = {0.80,0.80,0.80,1.};
|
||||
const float white[] = {0.95,0.95,0.95,1.};
|
||||
igl::opengl2::draw_floor_outline(grey,white);
|
||||
}
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_FLOOR_H
|
||||
#define IGL_OPENGL2_DRAW_FLOOR_H
|
||||
#include "../igl_inline.h"
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
|
||||
// Draw a checkerboard floor aligned with current (X,Z) plane using ../opengl/OpenGL_
|
||||
// calls. side=50 centered at (0,0):
|
||||
// (-25,-25)-->(-25,25)-->(25,25)-->(25,-25)
|
||||
//
|
||||
// Use glPushMatrix(), glScaled(), glTranslated() to arrange the floor.
|
||||
//
|
||||
// Inputs:
|
||||
// colorA float4 color
|
||||
// colorB float4 color
|
||||
//
|
||||
// Example:
|
||||
// // Draw a nice floor
|
||||
// glPushMatrix();
|
||||
// glCullFace(GL_BACK);
|
||||
// glEnable(GL_CULL_FACE);
|
||||
// glEnable(GL_LIGHTING);
|
||||
// glTranslated(0,-1,0);
|
||||
// if(project(Vector3d(0,0,0))(2) - project(Vector3d(0,1,0))(2) > -FLOAT_EPS)
|
||||
// {
|
||||
// draw_floor_outline();
|
||||
// }
|
||||
// draw_floor();
|
||||
// glPopMatrix();
|
||||
// glDisable(GL_CULL_FACE);
|
||||
//
|
||||
IGL_INLINE void draw_floor(
|
||||
const float * colorA,
|
||||
const float * colorB,
|
||||
const int GridSizeX=100,
|
||||
const int GridSizeY=100);
|
||||
// Wrapper with default colors
|
||||
IGL_INLINE void draw_floor();
|
||||
IGL_INLINE void draw_floor_outline(
|
||||
const float * colorA,
|
||||
const float * colorB,
|
||||
const int GridSizeX=100,
|
||||
const int GridSizeY=100);
|
||||
// Wrapper with default colors
|
||||
IGL_INLINE void draw_floor_outline();
|
||||
}
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_floor.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,278 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "draw_mesh.h"
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N)
|
||||
{
|
||||
using namespace Eigen;
|
||||
MatrixXd _d;
|
||||
MatrixXi _i;
|
||||
return draw_mesh(V,F,N,_i,_d,_d,_i,_d,0,_i,0);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C)
|
||||
{
|
||||
using namespace Eigen;
|
||||
MatrixXd _d;
|
||||
MatrixXi _i;
|
||||
return draw_mesh(V,F,N,_i,C,_d,_i,_d,0,_i,0);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC)
|
||||
{
|
||||
using namespace Eigen;
|
||||
MatrixXd _d;
|
||||
MatrixXi _i;
|
||||
return draw_mesh(V,F,N,_i,C,TC,_i,_d,0,_i,0);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC,
|
||||
const Eigen::MatrixXd & W,
|
||||
const GLuint W_index,
|
||||
const Eigen::MatrixXi & WI,
|
||||
const GLuint WI_index)
|
||||
{
|
||||
using namespace Eigen;
|
||||
return draw_mesh(V,F,N,MatrixXi(),C,TC,MatrixXi(),W,W_index,WI,WI_index);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXi & NF,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC,
|
||||
const Eigen::MatrixXi & TF,
|
||||
const Eigen::MatrixXd & W,
|
||||
const GLuint W_index,
|
||||
const Eigen::MatrixXi & WI,
|
||||
const GLuint WI_index)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
const int rF = F.rows();
|
||||
const int cF = F.cols();
|
||||
const int cC = C.cols();
|
||||
const int rC = C.rows();
|
||||
const int cW = W.cols();
|
||||
const int rW = W.rows();
|
||||
const int rV = V.rows();
|
||||
const int rTC = TC.rows();
|
||||
const int rTF = TF.rows();
|
||||
const int rNF = NF.rows();
|
||||
const int rN = N.rows();
|
||||
|
||||
if(F.size() > 0)
|
||||
{
|
||||
assert(F.maxCoeff() < V.rows());
|
||||
assert(V.cols() == 3);
|
||||
assert(rC == rV || rC == rF || rC == rF*3 || rC==1 || C.size() == 0);
|
||||
assert(C.cols() >= 3 || C.size() == 0);
|
||||
assert(N.cols() == 3 || N.size() == 0);
|
||||
assert(TC.cols() == 2 || TC.size() == 0);
|
||||
assert(cF == 3 || cF == 4);
|
||||
assert(TF.size() == 0 || TF.cols() == F.cols());
|
||||
assert(NF.size() == 0 || NF.cols() == NF.cols());
|
||||
}
|
||||
if(W.size()>0)
|
||||
{
|
||||
assert(W.rows() == V.rows());
|
||||
assert(WI.rows() == V.rows());
|
||||
assert(W.cols() == WI.cols());
|
||||
}
|
||||
|
||||
switch(F.cols())
|
||||
{
|
||||
default:
|
||||
case 3:
|
||||
glBegin(GL_TRIANGLES);
|
||||
break;
|
||||
case 4:
|
||||
glBegin(GL_QUADS);
|
||||
break;
|
||||
}
|
||||
// loop over faces
|
||||
for(int i = 0; i<rF;i++)
|
||||
{
|
||||
// loop over corners of triangle
|
||||
for(int j = 0;j<cF;j++)
|
||||
{
|
||||
|
||||
int tc = -1;
|
||||
if(rTF != 0)
|
||||
{
|
||||
tc = TF(i,j);
|
||||
} else if(rTC == 1)
|
||||
{
|
||||
tc = 0;
|
||||
}else if(rTC == rV)
|
||||
{
|
||||
tc = F(i,j);
|
||||
}else if(rTC == rF*cF)
|
||||
{
|
||||
tc = i*cF + j;
|
||||
}else if(rTC == rF)
|
||||
{
|
||||
tc = i;
|
||||
}else
|
||||
{
|
||||
assert(TC.size() == 0);
|
||||
}
|
||||
|
||||
// RGB(A)
|
||||
Matrix<MatrixXd::Scalar,1,Dynamic> color;
|
||||
if(rC == 1)
|
||||
{
|
||||
color = C.row(0);
|
||||
}else if(rC == rV)
|
||||
{
|
||||
color = C.row(F(i,j));
|
||||
}else if(rC == rF*cF)
|
||||
{
|
||||
color = C.row(i*cF+j);
|
||||
}else if(rC == rF)
|
||||
{
|
||||
color = C.row(i);
|
||||
}else
|
||||
{
|
||||
assert(C.size() == 0);
|
||||
}
|
||||
|
||||
int n = -1;
|
||||
if(rNF != 0)
|
||||
{
|
||||
n = NF(i,j); // indexed normals
|
||||
} else if(rN == 1)
|
||||
{
|
||||
n = 0; // uniform normals
|
||||
}else if(rN == rF)
|
||||
{
|
||||
n = i; // face normals
|
||||
}else if(rN == rV)
|
||||
{
|
||||
n = F(i,j); // vertex normals
|
||||
}else if(rN == rF*cF)
|
||||
{
|
||||
n = i*cF + j; // corner normals
|
||||
}else
|
||||
{
|
||||
assert(N.size() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
if(rW>0 && W_index !=0 && WI_index != 0)
|
||||
{
|
||||
int weights_left = cW;
|
||||
while(weights_left != 0)
|
||||
{
|
||||
int pass_size = std::min(4,weights_left);
|
||||
int weights_already_passed = cW-weights_left;
|
||||
// Get attribute location of next 4 weights
|
||||
int pass_W_index = W_index + weights_already_passed/4;
|
||||
int pass_WI_index = WI_index + weights_already_passed/4;
|
||||
switch(pass_size)
|
||||
{
|
||||
case 1:
|
||||
glVertexAttrib1d(
|
||||
pass_W_index,
|
||||
W(F(i,j),0+weights_already_passed));
|
||||
glVertexAttrib1d(
|
||||
pass_WI_index,
|
||||
WI(F(i,j),0+weights_already_passed));
|
||||
break;
|
||||
case 2:
|
||||
glVertexAttrib2d(
|
||||
pass_W_index,
|
||||
W(F(i,j),0+weights_already_passed),
|
||||
W(F(i,j),1+weights_already_passed));
|
||||
glVertexAttrib2d(
|
||||
pass_WI_index,
|
||||
WI(F(i,j),0+weights_already_passed),
|
||||
WI(F(i,j),1+weights_already_passed));
|
||||
break;
|
||||
case 3:
|
||||
glVertexAttrib3d(
|
||||
pass_W_index,
|
||||
W(F(i,j),0+weights_already_passed),
|
||||
W(F(i,j),1+weights_already_passed),
|
||||
W(F(i,j),2+weights_already_passed));
|
||||
glVertexAttrib3d(
|
||||
pass_WI_index,
|
||||
WI(F(i,j),0+weights_already_passed),
|
||||
WI(F(i,j),1+weights_already_passed),
|
||||
WI(F(i,j),2+weights_already_passed));
|
||||
break;
|
||||
default:
|
||||
glVertexAttrib4d(
|
||||
pass_W_index,
|
||||
W(F(i,j),0+weights_already_passed),
|
||||
W(F(i,j),1+weights_already_passed),
|
||||
W(F(i,j),2+weights_already_passed),
|
||||
W(F(i,j),3+weights_already_passed));
|
||||
glVertexAttrib4d(
|
||||
pass_WI_index,
|
||||
WI(F(i,j),0+weights_already_passed),
|
||||
WI(F(i,j),1+weights_already_passed),
|
||||
WI(F(i,j),2+weights_already_passed),
|
||||
WI(F(i,j),3+weights_already_passed));
|
||||
break;
|
||||
}
|
||||
weights_left -= pass_size;
|
||||
}
|
||||
}
|
||||
if(tc != -1)
|
||||
{
|
||||
glTexCoord2d(TC(tc,0),TC(tc,1));
|
||||
}
|
||||
if(rC>0)
|
||||
{
|
||||
switch(cC)
|
||||
{
|
||||
case 3:
|
||||
glColor3dv(color.data());
|
||||
break;
|
||||
case 4:
|
||||
glColor4dv(color.data());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(n != -1)
|
||||
{
|
||||
glNormal3d(N(n,0),N(n,1),N(n,2));
|
||||
}
|
||||
glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_MESH_H
|
||||
#define IGL_OPENGL2_DRAW_MESH_H
|
||||
#include "../igl_inline.h"
|
||||
#include "gl.h"
|
||||
#include <Eigen/Dense>
|
||||
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
|
||||
// Draw ../opengl/OpenGL_ commands needed to display a mesh with normals
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3|4 eigen Matrix of face (triangle/quad) indices
|
||||
// N #V|#F by 3 eigen Matrix of 3D normals
|
||||
IGL_INLINE void draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N);
|
||||
|
||||
// Draw ../opengl/OpenGL_ commands needed to display a mesh with normals and per-vertex
|
||||
// colors
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3|4 eigen Matrix of face (triangle/quad) indices
|
||||
// N #V|#F by 3 eigen Matrix of 3D normals
|
||||
// C #V|#F|1 by 3 eigen Matrix of RGB colors
|
||||
IGL_INLINE void draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C);
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3|4 eigen Matrix of face (triangle/quad) indices
|
||||
// N #V|#F by 3 eigen Matrix of 3D normals
|
||||
// C #V|#F|1 by 3 eigen Matrix of RGB colors
|
||||
// TC #V|#F|1 by 3 eigen Matrix of Texture Coordinates
|
||||
IGL_INLINE void draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC);
|
||||
|
||||
// Draw ../opengl/OpenGL_ commands needed to display a mesh with normals, per-vertex
|
||||
// colors and LBS weights
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3|4 eigen Matrix of face (triangle/quad) indices
|
||||
// N #V by 3 eigen Matrix of mesh vertex 3D normals
|
||||
// C #V by 3 eigen Matrix of mesh vertex RGB colors
|
||||
// TC #V by 3 eigen Matrix of mesh vertex UC coorindates between 0 and 1
|
||||
// W #V by #H eigen Matrix of per mesh vertex, per handle weights
|
||||
// W_index Specifies the index of the "weight" vertex attribute: see
|
||||
// glBindAttribLocation, if W_index is 0 then weights are ignored
|
||||
// WI #V by #H eigen Matrix of per mesh vertex, per handle weight ids
|
||||
// WI_index Specifies the index of the "weight" vertex attribute: see
|
||||
// glBindAttribLocation, if WI_index is 0 then weight indices are ignored
|
||||
IGL_INLINE void draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC,
|
||||
const Eigen::MatrixXd & W,
|
||||
const GLuint W_index,
|
||||
const Eigen::MatrixXi & WI,
|
||||
const GLuint WI_index);
|
||||
|
||||
// Draw ../opengl/OpenGL_ commands needed to display a mesh with normals, per-vertex
|
||||
// colors and LBS weights
|
||||
//
|
||||
// Inputs:
|
||||
// V #V by 3 eigen Matrix of mesh vertex 3D positions
|
||||
// F #F by 3|4 eigen Matrix of face (triangle/quad) indices
|
||||
// N #V by 3 eigen Matrix of mesh vertex 3D normals
|
||||
// NF #F by 3 eigen Matrix of face (triangle/quad) normal indices, <0
|
||||
// means no normal
|
||||
// C #V by 3 eigen Matrix of mesh vertex RGB colors
|
||||
// TC #V by 3 eigen Matrix of mesh vertex UC coorindates between 0 and 1
|
||||
// TF #F by 3 eigen Matrix of face (triangle/quad) texture indices, <0
|
||||
// means no texture
|
||||
// W #V by #H eigen Matrix of per mesh vertex, per handle weights
|
||||
// W_index Specifies the index of the "weight" vertex attribute: see
|
||||
// glBindAttribLocation, if W_index is 0 then weights are ignored
|
||||
// WI #V by #H eigen Matrix of per mesh vertex, per handle weight ids
|
||||
// WI_index Specifies the index of the "weight" vertex attribute: see
|
||||
// glBindAttribLocation, if WI_index is 0 then weight indices are ignored
|
||||
IGL_INLINE void draw_mesh(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixXd & N,
|
||||
const Eigen::MatrixXi & NF,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXd & TC,
|
||||
const Eigen::MatrixXi & TF,
|
||||
const Eigen::MatrixXd & W,
|
||||
const GLuint W_index,
|
||||
const Eigen::MatrixXi & WI,
|
||||
const GLuint WI_index);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_mesh.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "draw_point.h"
|
||||
|
||||
// Implementation
|
||||
#include "gl.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_point(
|
||||
const double x,
|
||||
const double y,
|
||||
const double z,
|
||||
const double requested_r,
|
||||
const bool selected)
|
||||
{
|
||||
// Push GL settings
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);
|
||||
|
||||
float f;
|
||||
glGetFloatv(GL_POINT_SIZE_MAX,&f);
|
||||
// THIS IS OVERZEALOUS on Mac OS X: OpenGL reports a smaller point size than
|
||||
// possible.
|
||||
//assert(requested_r<=0.5*f);
|
||||
double r = (requested_r<0.5*f?requested_r:0.5*f);
|
||||
|
||||
//glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// get current color
|
||||
float color[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR,color);
|
||||
|
||||
double outline_size = (r>7 ? sqrt(r/7.0) : 1.0);
|
||||
|
||||
// White outline
|
||||
glColor4f(1,1,1,color[3]);
|
||||
glPointSize(2*r);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(x,y,z);
|
||||
glEnd();
|
||||
// Black outline
|
||||
glColor4f(0,0,0,color[3]);
|
||||
glPointSize(2*r-2*outline_size);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(x,y,z);
|
||||
glEnd();
|
||||
|
||||
// Foreground
|
||||
glColor4fv(color);
|
||||
glPointSize(2*r-4*outline_size);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(x,y,z);
|
||||
glEnd();
|
||||
// Selection inner circle
|
||||
if(selected)
|
||||
{
|
||||
glColor4f(0,0,0,color[3]);
|
||||
double selected_size = 2*r-7*outline_size;
|
||||
selected_size = (selected_size>3?selected_size:3);
|
||||
glPointSize(selected_size);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(x,y,z);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// reset color
|
||||
glColor4fv(color);
|
||||
|
||||
// Pop GL settings
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
template <typename DerivedP>
|
||||
IGL_INLINE void igl::opengl2::draw_point(
|
||||
const Eigen::PlainObjectBase<DerivedP> & P,
|
||||
const double requested_r,
|
||||
const bool selected)
|
||||
{
|
||||
switch(P.size())
|
||||
{
|
||||
case 2:
|
||||
return draw_point(P(0),P(1),0,requested_r,selected);
|
||||
default:
|
||||
return draw_point(P(0),P(1),P(2),requested_r,selected);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::opengl2::draw_point<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, double, bool);
|
||||
template void igl::opengl2::draw_point<Eigen::Matrix<double, 2, 1, 0, 2, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> > const&, double, bool);
|
||||
#endif
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_POINT_H
|
||||
#define IGL_OPENGL2_DRAW_POINT_H
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
|
||||
//double POINT_COLOR[3] = {239./255.,213./255.,46./255.};
|
||||
// Draw a nice looking, colored dot at a given point in 3d.
|
||||
//
|
||||
// Note: expects that GL_CURRENT_COLOR is set with the desired foreground color
|
||||
//
|
||||
// Inputs:
|
||||
// x x-coordinate of point, modelview coordinates
|
||||
// y y-coordinate of point, modelview coordinates
|
||||
// z z-coordinate of point, modelview coordinates
|
||||
// requested_r outer-most radius of dot {7}, measured in screen space pixels
|
||||
// selected fills inner circle with black {false}
|
||||
// Asserts that requested_r does not exceed 0.5*GL_POINT_SIZE_MAX
|
||||
IGL_INLINE void draw_point(
|
||||
const double x,
|
||||
const double y,
|
||||
const double z,
|
||||
const double requested_r = 7,
|
||||
const bool selected = false);
|
||||
template <typename DerivedP>
|
||||
IGL_INLINE void draw_point(
|
||||
const Eigen::PlainObjectBase<DerivedP> & P,
|
||||
const double requested_r = 7,
|
||||
const bool selected = false);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_point.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
#include "draw_rectangular_marquee.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "../material_colors.h"
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_rectangular_marquee(
|
||||
const int from_x,
|
||||
const int from_y,
|
||||
const int to_x,
|
||||
const int to_y)
|
||||
{
|
||||
using namespace std;
|
||||
int l;
|
||||
glGetIntegerv(GL_LIGHTING,&l);
|
||||
int s;
|
||||
glGetIntegerv(GL_LINE_STIPPLE,&s);
|
||||
double lw;
|
||||
glGetDoublev(GL_LINE_WIDTH,&lw);
|
||||
glDisable(GL_LIGHTING);
|
||||
// Screen space for this viewport
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT,viewport);
|
||||
const int width = viewport[2];
|
||||
const int height = viewport[3];
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0,width,0,height);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
glLineStipple(3,0xAAAA);
|
||||
glLineWidth(1);
|
||||
glColor4f(0.2,0.2,0.2,1);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2d(from_x,from_y);
|
||||
glVertex2d(to_x,from_y);
|
||||
glVertex2d(to_x,to_y);
|
||||
glVertex2d(from_x,to_y);
|
||||
glVertex2d(from_x,from_y);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLineWidth(lw);
|
||||
(s ? glEnable(GL_LINE_STIPPLE):glDisable(GL_LINE_STIPPLE));
|
||||
(l ? glEnable(GL_LIGHTING):glDisable(GL_LIGHTING));
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_RECTANGULAR_MARQUEE_H
|
||||
#define IGL_OPENGL2_DRAW_RECTANGULAR_MARQUEE_H
|
||||
#include "../igl_inline.h"
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Draw a rectangular marquee (selection box) in screen space. This sets up
|
||||
// screen space using current viewport.
|
||||
//
|
||||
// Inputs:
|
||||
// from_x x coordinate of from point
|
||||
// from_y y coordinate of from point
|
||||
// to_x x coordinate of to point
|
||||
// to_y y coordinate of to point
|
||||
IGL_INLINE void draw_rectangular_marquee(
|
||||
const int from_x,
|
||||
const int from_y,
|
||||
const int to_x,
|
||||
const int to_y);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_rectangular_marquee.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,166 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "draw_skeleton_3d.h"
|
||||
#include "../PI.h"
|
||||
#include "../material_colors.h"
|
||||
#include "gl.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
template <
|
||||
typename DerivedC,
|
||||
typename DerivedBE,
|
||||
typename DerivedT,
|
||||
typename Derivedcolor>
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T,
|
||||
const Eigen::PlainObjectBase<Derivedcolor> & color,
|
||||
const double half_bbd)
|
||||
{
|
||||
// Note: Maya's skeleton *does* scale with the mesh suggesting a scale
|
||||
// parameter. Further, its joint balls are not rotated with the bones.
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
if(color.size() == 0)
|
||||
{
|
||||
return draw_skeleton_3d(C,BE,T,MAYA_SEA_GREEN,half_bbd);
|
||||
}
|
||||
assert(color.cols() == 4 || color.size() == 4);
|
||||
if(T.size() == 0)
|
||||
{
|
||||
typedef Eigen::Matrix<typename DerivedT::Scalar,Dynamic,Dynamic> Mat;
|
||||
Mat I = Mat::Identity(C.cols()+1,C.cols());
|
||||
Mat T = I.replicate(BE.rows(),1);
|
||||
// insane base case
|
||||
if(T.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return draw_skeleton_3d(C,BE,T,color,half_bbd);
|
||||
}
|
||||
assert(T.rows() == BE.rows()*(C.cols()+1));
|
||||
assert(T.cols() == C.cols());
|
||||
// push old settings
|
||||
glPushAttrib(GL_LIGHTING_BIT);
|
||||
glPushAttrib(GL_LINE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(1.0);
|
||||
|
||||
auto draw_sphere = [](const double r)
|
||||
{
|
||||
auto draw_circle = []()
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for(double th = 0;th<2.0*igl::PI;th+=(2.0*igl::PI/30.0))
|
||||
{
|
||||
glVertex3d(cos(th),sin(th),0.0);
|
||||
}
|
||||
glVertex3d(cos(0),sin(0),0.0);
|
||||
glEnd();
|
||||
};
|
||||
glPushMatrix();
|
||||
glScaled(r,r,r);
|
||||
draw_circle();
|
||||
glRotated(90.0,1.0,0.0,0.0);
|
||||
draw_circle();
|
||||
glRotated(90.0,0.0,1.0,0.0);
|
||||
draw_circle();
|
||||
glPopMatrix();
|
||||
};
|
||||
auto draw_pyramid = []()
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3d(0, 1,-1);
|
||||
glVertex3d(0,-1,-1);
|
||||
glVertex3d(0,-1, 1);
|
||||
glVertex3d(0, 1, 1);
|
||||
glVertex3d(0, 1,-1);
|
||||
glEnd();
|
||||
glBegin(GL_LINES);
|
||||
glVertex3d(0, 1,-1);
|
||||
glVertex3d(1,0,0);
|
||||
glVertex3d(0,-1,-1);
|
||||
glVertex3d(1,0,0);
|
||||
glVertex3d(0,-1, 1);
|
||||
glVertex3d(1,0,0);
|
||||
glVertex3d(0, 1, 1);
|
||||
glVertex3d(1,0,0);
|
||||
glEnd();
|
||||
};
|
||||
|
||||
// Loop over bones
|
||||
for(int e = 0;e < BE.rows();e++)
|
||||
{
|
||||
// Draw a sphere
|
||||
auto s = C.row(BE(e,0));
|
||||
auto d = C.row(BE(e,1));
|
||||
auto b = (d-s).transpose().eval();
|
||||
double r = 0.02*half_bbd;
|
||||
Matrix4d Te = Matrix4d::Identity();
|
||||
Te.block(0,0,3,4) = T.block(e*4,0,4,3).transpose();
|
||||
Quaterniond q;
|
||||
q.setFromTwoVectors(Vector3d(1,0,0),b);
|
||||
glPushMatrix();
|
||||
glMultMatrixd(Te.data());
|
||||
glTranslated(s(0),s(1),s(2));
|
||||
if(color.size() == 4)
|
||||
{
|
||||
glColor4d( color(0), color(1), color(2), color(3));
|
||||
}else
|
||||
{
|
||||
glColor4d( color(e,0), color(e,1), color(e,2), color(e,3));
|
||||
}
|
||||
draw_sphere(r);
|
||||
const double len = b.norm()-2.*r;
|
||||
if(len>=0)
|
||||
{
|
||||
auto u = b.normalized()*r;
|
||||
glPushMatrix();
|
||||
glTranslated(u(0),u(1),u(2));
|
||||
glMultMatrixd(Affine3d(q).matrix().data());
|
||||
glScaled(b.norm()-2.*r,r,r);
|
||||
draw_pyramid();
|
||||
glPopMatrix();
|
||||
}
|
||||
glTranslated(b(0),b(1),b(2));
|
||||
draw_sphere(r);
|
||||
glPopMatrix();
|
||||
}
|
||||
// Reset settings
|
||||
glPopAttrib();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T)
|
||||
{
|
||||
return draw_skeleton_3d(C,BE,T,MAYA_SEA_GREEN);
|
||||
}
|
||||
|
||||
template <typename DerivedC, typename DerivedBE>
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE)
|
||||
{
|
||||
return draw_skeleton_3d(C,BE,Eigen::MatrixXd(),MAYA_SEA_GREEN);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::opengl2::draw_skeleton_3d<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
|
||||
template void igl::opengl2::draw_skeleton_3d<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&);
|
||||
template void igl::opengl2::draw_skeleton_3d<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 4, 1, 0, 4, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 4, 1, 0, 4, 1> > const&, double);
|
||||
template void igl::opengl2::draw_skeleton_3d<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, double);
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_SKELETON_3D_H
|
||||
#define IGL_OPENGL2_DRAW_SKELETON_3D_H
|
||||
#include "../igl_inline.h"
|
||||
#include "../material_colors.h"
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
|
||||
// Draw a skeleton
|
||||
//
|
||||
// Inputs:
|
||||
// C #C by dim List of joint rest positions
|
||||
// BE #BE by 2 list of bone edge indices into C
|
||||
// T #BE*(dim+1) by dim matrix of stacked transposed bone transformations
|
||||
// color #BE|1 by 4 list of color
|
||||
// half_bbd half bounding box diagonal to determine scaling {1.0}
|
||||
template <
|
||||
typename DerivedC,
|
||||
typename DerivedBE,
|
||||
typename DerivedT,
|
||||
typename Derivedcolor>
|
||||
IGL_INLINE void draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T,
|
||||
const Eigen::PlainObjectBase<Derivedcolor> & color,
|
||||
const double half_bbd=0.5);
|
||||
// Default color
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T);
|
||||
template <typename DerivedC, typename DerivedBE>
|
||||
IGL_INLINE void draw_skeleton_3d(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_skeleton_3d.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,122 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "draw_skeleton_vector_graphics.h"
|
||||
#include "draw_point.h"
|
||||
#include "gl.h"
|
||||
#include "../material_colors.h"
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_vector_graphics(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE)
|
||||
{
|
||||
return draw_skeleton_vector_graphics(C,BE,BBW_POINT_COLOR,BBW_LINE_COLOR);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_vector_graphics(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const float * point_color,
|
||||
const float * line_color)
|
||||
{
|
||||
using namespace Eigen;
|
||||
|
||||
int old_lighting=0;
|
||||
double old_line_width=1;
|
||||
glGetIntegerv(GL_LIGHTING,&old_lighting);
|
||||
glGetDoublev(GL_LINE_WIDTH,&old_line_width);
|
||||
int cm;
|
||||
glGetIntegerv(GL_COLOR_MATERIAL,&cm);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
//glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glLineWidth(10.0);
|
||||
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
|
||||
float mat_ambient[4] = {0.1,0.1,0.1,1.0};
|
||||
float mat_specular[4] = {0.0,0.0,0.0,1.0};
|
||||
float mat_shininess = 1;
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
|
||||
|
||||
for(int i = 0;i<3;i++)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: glColor3fv(WHITE); glLineWidth(10); break;
|
||||
case 1: glColor3fv(BLACK); glLineWidth( 6); break;
|
||||
case 2: glColor3fv(line_color); glLineWidth( 4); break;
|
||||
}
|
||||
// Loop over bone edges
|
||||
glBegin(GL_LINES);
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
RowVector3d tip = C.row(BE(e,0));
|
||||
RowVector3d tail = C.row(BE(e,1));
|
||||
glVertex3dv(tip.data());
|
||||
glVertex3dv(tail.data());
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glColor3fv(point_color);
|
||||
for(int i = 0;i<C.rows();i++)
|
||||
{
|
||||
RowVector3d p = C.row(i);
|
||||
draw_point(p(0),p(1),p(2));
|
||||
}
|
||||
|
||||
(cm ? glEnable(GL_COLOR_MATERIAL):glDisable(GL_COLOR_MATERIAL));
|
||||
//glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glEnable(GL_LIGHTING);
|
||||
(old_lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING));
|
||||
glLineWidth(old_line_width);
|
||||
}
|
||||
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_vector_graphics(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T)
|
||||
{
|
||||
return draw_skeleton_vector_graphics(C,BE,T,BBW_POINT_COLOR,BBW_LINE_COLOR);
|
||||
}
|
||||
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void igl::opengl2::draw_skeleton_vector_graphics(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T,
|
||||
const float * point_color,
|
||||
const float * line_color)
|
||||
{
|
||||
DerivedC CT;
|
||||
DerivedBE BET;
|
||||
const int dim = T.cols();
|
||||
assert(dim == C.cols());
|
||||
CT.resize(2*BE.rows(),C.cols());
|
||||
BET.resize(BE.rows(),2);
|
||||
for(int e = 0;e<BE.rows();e++)
|
||||
{
|
||||
BET(e,0) = 2*e;
|
||||
BET(e,1) = 2*e+1;
|
||||
const auto & c0 = C.row(BE(e,0));
|
||||
const auto & c1 = C.row(BE(e,1));
|
||||
const auto & L = T.block(e*(dim+1),0,dim,dim);
|
||||
const auto & t = T.block(e*(dim+1)+dim,0,1,dim);
|
||||
CT.row(2*e) = c0 * L + t;
|
||||
CT.row(2*e+1) = c1 * L + t;
|
||||
}
|
||||
draw_skeleton_vector_graphics(CT,BET,point_color,line_color);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::opengl2::draw_skeleton_vector_graphics<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&);
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_DRAW_SKELETON_VECTOR_GRAPHICS_H
|
||||
#define IGL_OPENGL2_DRAW_SKELETON_VECTOR_GRAPHICS_H
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Draw a skeleton with a 2D vector graphcis style à la BBW, STBS, Monotonic,
|
||||
// FAST papers.
|
||||
//
|
||||
// Inputs:
|
||||
// C #C by dim list of joint positions
|
||||
// BE #BE by 2 list of bone edge indices into C
|
||||
// point_color color of points
|
||||
// line_color color of lines
|
||||
IGL_INLINE void draw_skeleton_vector_graphics(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const float * point_color,
|
||||
const float * line_color);
|
||||
// Use default colors (originally from BBW paper)
|
||||
IGL_INLINE void draw_skeleton_vector_graphics(
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::MatrixXi & BE);
|
||||
// T #BE*(dim+1) by dim matrix of stacked transposed bone transformations
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void draw_skeleton_vector_graphics(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T,
|
||||
const float * point_color,
|
||||
const float * line_color);
|
||||
template <typename DerivedC, typename DerivedBE, typename DerivedT>
|
||||
IGL_INLINE void draw_skeleton_vector_graphics(
|
||||
const Eigen::PlainObjectBase<DerivedC> & C,
|
||||
const Eigen::PlainObjectBase<DerivedBE> & BE,
|
||||
const Eigen::PlainObjectBase<DerivedT> & T);
|
||||
}
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "draw_skeleton_vector_graphics.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
0455195ebe076c34d28e9bfa34e2e0ec6b117571
|
||||
@@ -1,44 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_GL_H
|
||||
#define IGL_OPENGL2_GL_H
|
||||
|
||||
#ifdef IGL_OPENGL_GL_H
|
||||
# error "igl/opengl/gl.h already included"
|
||||
#endif
|
||||
|
||||
// Always use this:
|
||||
// #include "gl.h"
|
||||
// Instead of:
|
||||
// #include <OpenGL/gl.h>
|
||||
// or
|
||||
// #include <GL/gl.h>
|
||||
//
|
||||
|
||||
// For now this includes glu, glew and glext (perhaps these should be
|
||||
// separated)
|
||||
#ifdef _WIN32
|
||||
# define NOMINMAX
|
||||
# include <Windows.h>
|
||||
# undef DrawText
|
||||
# undef NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
# define GLEW_STATIC
|
||||
# include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/gl.h>
|
||||
# define __gl_h_ /* Prevent inclusion of the old gl.h */
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2017 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL_GLEXT_H
|
||||
#define IGL_OPENGL_GLEXT_H
|
||||
|
||||
#ifdef IGL_OPENGL2_GLEXT_H
|
||||
# error "igl/opengl2/glext.h already included"
|
||||
#endif
|
||||
|
||||
// Always use this:
|
||||
// #include "gl.h"
|
||||
// Instead of:
|
||||
// #include <OpenGL/glext.h>
|
||||
// or
|
||||
// #include <GL/glext.h>
|
||||
//
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/glext.h>
|
||||
#elif _WIN32
|
||||
// do nothing(?)
|
||||
#else
|
||||
# include <GL/glext.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2017 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_GLU_H
|
||||
#define IGL_OPENGL2_GLU_H
|
||||
|
||||
#ifdef IGL_OPENGL_GLU_H
|
||||
# error "igl/opengl/glu.h already included"
|
||||
#endif
|
||||
|
||||
// Always use this:
|
||||
// #include "glu.h"
|
||||
// Instead of:
|
||||
// #include <OpenGL/glu.h>
|
||||
// or
|
||||
// #include <GL/glu.h>
|
||||
//
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/glu.h>
|
||||
#else
|
||||
# include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "lens_flare.h"
|
||||
|
||||
#include "../C_STR.h"
|
||||
#include "unproject.h"
|
||||
#include "project.h"
|
||||
#include "shine_textures.h"
|
||||
#include "flare_textures.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
||||
// http://www.opengl.org/archives/resources/features/KilgardTechniques/LensFlare/glflare.c
|
||||
|
||||
IGL_INLINE void igl::opengl2::lens_flare_load_textures(
|
||||
std::vector<GLuint> & shine_id,
|
||||
std::vector<GLuint> & flare_id)
|
||||
{
|
||||
|
||||
const auto setup_texture =[](
|
||||
const uint8_t * texture,
|
||||
const int width,
|
||||
const int height,
|
||||
GLuint texobj,
|
||||
GLenum minFilter, GLenum maxFilter)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texobj);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, texture);
|
||||
};
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
shine_id.resize(10);
|
||||
glGenTextures(10,&shine_id[0]);
|
||||
for (int i = 0; i < (int)shine_id.size(); i++) {
|
||||
setup_texture(
|
||||
SHINE_TEXTURES[i],
|
||||
SHINE_TEXTURE_WIDTHS[i],
|
||||
SHINE_TEXTURE_HEIGHTS[i],
|
||||
shine_id[i], GL_LINEAR, GL_LINEAR);
|
||||
}
|
||||
flare_id.resize(6);
|
||||
glGenTextures(6,&flare_id[0]);
|
||||
for (int i = 0; i < (int)flare_id.size(); i++) {
|
||||
setup_texture(
|
||||
FLARE_TEXTURES[i],
|
||||
FLARE_TEXTURE_WIDTHS[i],
|
||||
FLARE_TEXTURE_HEIGHTS[i],
|
||||
flare_id[i], GL_LINEAR, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::lens_flare_create(
|
||||
const float * A,
|
||||
const float * B,
|
||||
const float * C,
|
||||
std::vector<igl::opengl2::Flare> & flares)
|
||||
{
|
||||
using namespace std;
|
||||
flares.resize(12);
|
||||
/* Shines */
|
||||
flares[0] = Flare(-1, 1.0f, 0.1f, C, 1.0);
|
||||
flares[1] = Flare(-1, 1.0f, 0.15f, B, 1.0);
|
||||
flares[2] = Flare(-1, 1.0f, 0.35f, A, 1.0);
|
||||
|
||||
/* Flares */
|
||||
flares[3] = Flare(2, 1.3f, 0.04f, A, 0.6);
|
||||
flares[4] = Flare(3, 1.0f, 0.1f, A, 0.4);
|
||||
flares[5] = Flare(1, 0.5f, 0.2f, A, 0.3);
|
||||
flares[6] = Flare(3, 0.2f, 0.05f, A, 0.3);
|
||||
flares[7] = Flare(0, 0.0f, 0.04f, A, 0.3);
|
||||
flares[8] = Flare(5, -0.25f, 0.07f, A, 0.5);
|
||||
flares[9] = Flare(5, -0.4f, 0.02f, A, 0.6);
|
||||
flares[10] = Flare(5, -0.6f, 0.04f, A, 0.4);
|
||||
flares[11] = Flare(5, -1.0f, 0.03f, A, 0.2);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::lens_flare_draw(
|
||||
const std::vector<igl::opengl2::Flare> & flares,
|
||||
const std::vector<GLuint> & shine_ids,
|
||||
const std::vector<GLuint> & flare_ids,
|
||||
const Eigen::Vector3f & light,
|
||||
const float near_clip,
|
||||
int & shine_tic)
|
||||
{
|
||||
bool ot2 = glIsEnabled(GL_TEXTURE_2D);
|
||||
bool ob = glIsEnabled(GL_BLEND);
|
||||
bool odt = glIsEnabled(GL_DEPTH_TEST);
|
||||
bool ocm = glIsEnabled(GL_COLOR_MATERIAL);
|
||||
bool ol = glIsEnabled(GL_LIGHTING);
|
||||
int obsa,obda,odf,odwm;
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA,&obsa);
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA,&obda);
|
||||
glGetIntegerv(GL_DEPTH_FUNC,&odf);
|
||||
glGetIntegerv(GL_DEPTH_WRITEMASK,&odwm);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
//glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
|
||||
//// view_dir direction from eye to position it is looking at
|
||||
//const Vector3f view_dir = (at - from).normalized();
|
||||
|
||||
//// near_clip distance from eye to near clipping plane along view_dir
|
||||
//// center position on near clipping plane along viewdir from eye
|
||||
//const Vector3f center = from + near_clip*view_dir;
|
||||
|
||||
Vector3f plight = project(light);
|
||||
// Orthogonal vectors to view direction at light
|
||||
Vector3f psx = plight;
|
||||
psx(0) += 1;
|
||||
Vector3f psy = plight;
|
||||
psy(1) += 1;
|
||||
|
||||
// axis toward center
|
||||
int vp[4];
|
||||
glGetIntegerv(GL_VIEWPORT,vp);
|
||||
Vector3f center = unproject(Vector3f(0.5*vp[2],0.5*vp[3],plight[2]-1e-3));
|
||||
//Vector3f center(0,0,1);
|
||||
Vector3f axis = light-center;
|
||||
//glLineWidth(4.);
|
||||
//glColor3f(1,0,0);
|
||||
//glBegin(GL_LINES);
|
||||
//glVertex3fv(center.data());
|
||||
//glVertex3fv(light.data());
|
||||
//glEnd();
|
||||
|
||||
const Vector3f SX = unproject(psx).normalized();
|
||||
const Vector3f SY = unproject(psy).normalized();
|
||||
|
||||
for(int i = 0; i < (int)flares.size(); i++)
|
||||
{
|
||||
const Vector3f sx = flares[i].scale * SX;
|
||||
const Vector3f sy = flares[i].scale * SY;
|
||||
glColor3fv(flares[i].color);
|
||||
if (flares[i].type < 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, shine_ids[shine_tic]);
|
||||
shine_tic = (shine_tic + 1) % shine_ids.size();
|
||||
} else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, flare_ids[flares[i].type]);
|
||||
}
|
||||
|
||||
/* position = center + flare[i].loc * axis */
|
||||
const Vector3f position = center + flares[i].loc * axis;
|
||||
Vector3f tmp;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
tmp = position + sx;
|
||||
tmp = tmp + sy;
|
||||
glVertex3fv(tmp.data());
|
||||
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
tmp = position - sx;
|
||||
tmp = tmp + sy;
|
||||
glVertex3fv(tmp.data());
|
||||
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
tmp = position - sx;
|
||||
tmp = tmp - sy;
|
||||
glVertex3fv(tmp.data());
|
||||
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
tmp = position + sx;
|
||||
tmp = tmp - sy;
|
||||
glVertex3fv(tmp.data());
|
||||
glEnd();
|
||||
}
|
||||
ot2?glEnable(GL_TEXTURE_2D):glDisable(GL_TEXTURE_2D);
|
||||
ob?glEnable(GL_BLEND):glDisable(GL_BLEND);
|
||||
odt?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST);
|
||||
ocm?glEnable(GL_COLOR_MATERIAL):glDisable(GL_COLOR_MATERIAL);
|
||||
ol?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING);
|
||||
glBlendFunc(obsa,obda);
|
||||
glDepthFunc(odf);
|
||||
glDepthMask(odwm);
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_LENS_FLARE_H
|
||||
#define IGL_OPENGL2_LENS_FLARE_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include "gl.h"
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
|
||||
struct Flare{
|
||||
int type; /* flare texture index, 0..5 */
|
||||
float scale;
|
||||
float loc; /* position on axis */
|
||||
float color[3];
|
||||
Flare():
|
||||
type(-1),
|
||||
scale(0),
|
||||
loc(0)
|
||||
{}
|
||||
Flare(int type, float location, float scale, const float color[3], float colorScale) :
|
||||
type(type),
|
||||
scale(scale),
|
||||
loc(location)
|
||||
{
|
||||
this->color[0] = color[0] * colorScale;
|
||||
this->color[1] = color[1] * colorScale;
|
||||
this->color[2] = color[2] * colorScale;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Initialize shared data for lens flates
|
||||
//
|
||||
// Inputs:
|
||||
// start_id starting texture id location (should have at least id:id+16 free)
|
||||
// Outputs:
|
||||
// shine list of texture ids for shines
|
||||
// flare list of texture ids for flares
|
||||
IGL_INLINE void lens_flare_load_textures(
|
||||
std::vector<GLuint> & shine_ids,
|
||||
std::vector<GLuint> & flare_ids);
|
||||
|
||||
// Create a set of lens flares
|
||||
//
|
||||
// Inputs:
|
||||
// A primary color
|
||||
// B secondary color
|
||||
// C secondary color
|
||||
// Outputs:
|
||||
// flares list of flare objects
|
||||
IGL_INLINE void lens_flare_create(
|
||||
const float * A,
|
||||
const float * B,
|
||||
const float * C,
|
||||
std::vector<Flare> & flares);
|
||||
|
||||
// Draw lens flares
|
||||
//
|
||||
// Inputs:
|
||||
// flares list of Flare objects
|
||||
// shine_ids list of shine textures
|
||||
// flare_ids list of flare texture ids
|
||||
// light position of light
|
||||
// near_clip near clipping plane
|
||||
// shine_tic current "tic" in shine textures
|
||||
// Outputs:
|
||||
// shine_tic current "tic" in shine textures
|
||||
IGL_INLINE void lens_flare_draw(
|
||||
const std::vector<Flare> & flares,
|
||||
const std::vector<GLuint> & shine_ids,
|
||||
const std::vector<GLuint> & flare_ids,
|
||||
const Eigen::Vector3f & light,
|
||||
const float near_clip,
|
||||
int & shine_tic);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "lens_flare.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "model_proj_viewport.h"
|
||||
#include "gl.h"
|
||||
|
||||
template <typename Derivedmodel, typename Derivedproj, typename Derivedviewport>
|
||||
IGL_INLINE void igl::opengl2::model_proj_viewport(
|
||||
Eigen::PlainObjectBase<Derivedmodel> & model,
|
||||
Eigen::PlainObjectBase<Derivedproj> & proj,
|
||||
Eigen::PlainObjectBase<Derivedviewport> & viewport)
|
||||
{
|
||||
Eigen::Matrix4d MV,P;
|
||||
Eigen::Vector4i VPi;
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX,MV.data());
|
||||
glGetDoublev(GL_PROJECTION_MATRIX,P.data());
|
||||
glGetIntegerv(GL_VIEWPORT,VPi.data());
|
||||
viewport = VPi.cast<typename Derivedviewport::Scalar>();
|
||||
model = MV.cast<typename Derivedmodel::Scalar>();
|
||||
proj = P.cast<typename Derivedproj::Scalar>();
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::opengl2::model_proj_viewport<Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 1, 0, 4, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
|
||||
template void igl::opengl2::model_proj_viewport<Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 1, 0, 4, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, 4, 1, 0, 4, 1> >&);
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_MODEL_PROJ_VIEW_H
|
||||
#define IGL_OPENGL2_MODEL_PROJ_VIEW_H
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Collect the model-view, projection and viewport matrices
|
||||
//
|
||||
// Outputs:
|
||||
// model 4x4 modelview matrix
|
||||
// proj 4x4 projection matrix
|
||||
// viewport 4x1 viewport vector
|
||||
//
|
||||
template <typename Derivedmodel, typename Derivedproj, typename Derivedviewport>
|
||||
IGL_INLINE void model_proj_viewport(
|
||||
Eigen::PlainObjectBase<Derivedmodel> & model,
|
||||
Eigen::PlainObjectBase<Derivedproj> & proj,
|
||||
Eigen::PlainObjectBase<Derivedviewport> & viewport);
|
||||
}
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "model_proj_viewport.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "print_gl_get.h"
|
||||
|
||||
#include <cstdio>
|
||||
IGL_INLINE void igl::opengl2::print_gl_get(GLenum pname)
|
||||
{
|
||||
double dM[16];
|
||||
|
||||
int rows = 4;
|
||||
int cols = 4;
|
||||
switch(pname)
|
||||
{
|
||||
case GL_MODELVIEW_MATRIX:
|
||||
case GL_PROJECTION_MATRIX:
|
||||
{
|
||||
rows = 4;
|
||||
cols = 4;
|
||||
glGetDoublev(pname,dM);
|
||||
for(int i = 0;i<rows;i++)
|
||||
{
|
||||
for(int j = 0;j<cols;j++)
|
||||
{
|
||||
printf("%lg ",dM[j*rows+i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr,"ERROR in print_gl_get(), gl enum not recognized.\n");
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_PRINT_GL_GET_H
|
||||
#define IGL_OPENGL2_PRINT_GL_GET_H
|
||||
#include "gl.h"
|
||||
#include "../igl_inline.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Prints the value of pname found by issuing glGet*(pname,*)
|
||||
// Inputs:
|
||||
// pname enum key to gl parameter
|
||||
IGL_INLINE void print_gl_get(GLenum pname);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "print_gl_get.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,73 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "project.h"
|
||||
#include "../project.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include <iostream>
|
||||
|
||||
IGL_INLINE int igl::opengl2::project(
|
||||
const double objX,
|
||||
const double objY,
|
||||
const double objZ,
|
||||
double* winX,
|
||||
double* winY,
|
||||
double* winZ)
|
||||
{
|
||||
using namespace std;
|
||||
// Put model, projection, and viewport matrices into double arrays
|
||||
double MV[16];
|
||||
double P[16];
|
||||
int VP[4];
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, MV);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, P);
|
||||
glGetIntegerv(GL_VIEWPORT, VP);
|
||||
int ret = gluProject(objX,objY,objZ,MV,P,VP,winX,winY,winZ);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Derivedobj, typename Derivedwin>
|
||||
IGL_INLINE int igl::opengl2::project(
|
||||
const Eigen::PlainObjectBase<Derivedobj> & obj,
|
||||
Eigen::PlainObjectBase<Derivedwin> & win)
|
||||
{
|
||||
assert(obj.size() >= 3);
|
||||
Eigen::Vector3d dobj(obj(0),obj(1),obj(2));
|
||||
Eigen::Vector3d dwin;
|
||||
int ret = igl::opengl2::project(dobj(0),dobj(1),dobj(2),
|
||||
&dwin.data()[0],
|
||||
&dwin.data()[1],
|
||||
&dwin.data()[2]);
|
||||
win(0) = dwin(0);
|
||||
win(1) = dwin(1);
|
||||
win(2) = dwin(2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Derivedobj>
|
||||
IGL_INLINE Derivedobj igl::opengl2::project(
|
||||
const Eigen::PlainObjectBase<Derivedobj> & obj)
|
||||
{
|
||||
Derivedobj win;
|
||||
igl::opengl2::project(obj,win);
|
||||
return win;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template int igl::opengl2::project<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
|
||||
template int igl::opengl2::project<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
|
||||
template int igl::opengl2::project<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
|
||||
template Eigen::Matrix<double, 3, 1, 0, 3, 1> igl::opengl2::project<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&);
|
||||
template Eigen::Matrix<float, 3, 1, 0, 3, 1> igl::opengl2::project<Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&);
|
||||
template Eigen::Matrix<double, 1, -1, 1, 1, -1> igl::opengl2::project<Eigen::Matrix<double, 1, -1, 1, 1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&);
|
||||
template Eigen::Matrix<double, 1, 3, 1, 1, 3> igl::opengl2::project<Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&);
|
||||
template Eigen::Matrix<double, 1, 2, 1, 1, 2> igl::opengl2::project<Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&);
|
||||
template Eigen::Matrix<double, 2, 1, 0, 2, 1> igl::opengl2::project<Eigen::Matrix<double, 2, 1, 0, 2, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> > const&);
|
||||
#endif
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_PROJECT_H
|
||||
#define IGL_OPENGL2_PROJECT_H
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Dense>
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Wrapper for gluProject that uses the current GL_MODELVIEW_MATRIX,
|
||||
// GL_PROJECTION_MATRIX, and GL_VIEWPORT
|
||||
// Inputs:
|
||||
// obj* 3D objects' x, y, and z coordinates respectively
|
||||
// Outputs:
|
||||
// win* pointers to screen space x, y, and z coordinates respectively
|
||||
// Returns return value of gluProject call
|
||||
IGL_INLINE int project(
|
||||
const double objX,
|
||||
const double objY,
|
||||
const double objZ,
|
||||
double* winX,
|
||||
double* winY,
|
||||
double* winZ);
|
||||
// Eigen wrapper
|
||||
template <typename Derivedobj, typename Derivedwin>
|
||||
IGL_INLINE int project(
|
||||
const Eigen::PlainObjectBase<Derivedobj> & obj,
|
||||
Eigen::PlainObjectBase<Derivedwin> & win);
|
||||
// Eigen wrapper with return
|
||||
template <typename Derivedobj>
|
||||
IGL_INLINE Derivedobj project(
|
||||
const Eigen::PlainObjectBase<Derivedobj> & obj);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "project.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "right_axis.h"
|
||||
#include "gl.h"
|
||||
|
||||
IGL_INLINE void igl::opengl2::right_axis(double * x, double * y, double * z)
|
||||
{
|
||||
double mv[16];
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, mv);
|
||||
igl::opengl2::right_axis(mv,x,y,z);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::opengl2::right_axis(const double * mv,double * x, double * y, double * z)
|
||||
{
|
||||
*x = -mv[0*4+0];
|
||||
*y = -mv[1*4+0];
|
||||
*z = -mv[2*4+0];
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#ifndef IGL_OPENGL2_RIGHT_AXIS_H
|
||||
#define IGL_OPENGL2_RIGHT_AXIS_H
|
||||
#include "../igl_inline.h"
|
||||
namespace igl
|
||||
{
|
||||
namespace opengl2
|
||||
{
|
||||
// Determines the right axis or depth axis of the current gl matrix
|
||||
// Outputs:
|
||||
// x pointer to x-coordinate in scene coordinates of the un-normalized
|
||||
// right axis
|
||||
// y pointer to y-coordinate in scene coordinates of the un-normalized
|
||||
// right axis
|
||||
// z pointer to z-coordinate in scene coordinates of the un-normalized
|
||||
// right axis
|
||||
// mv pointer to modelview matrix
|
||||
//
|
||||
// Note: Right axis is returned *UN-normalized*
|
||||
IGL_INLINE void right_axis(double * x, double * y, double * z);
|
||||
IGL_INLINE void right_axis(const double * mv, double * x, double * y, double * z);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "right_axis.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
05001989d8ff527cd57823f435ec025540ebf18e
|
||||
@@ -1,80 +0,0 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "sort_triangles.h"
|
||||
#include "project.h"
|
||||
#include "../sort_triangles.h"
|
||||
#include "gl.h"
|
||||
#include "../sort.h"
|
||||
#include "../slice.h"
|
||||
#include "../barycenter.h"
|
||||
#include <iostream>
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedFF,
|
||||
typename DerivedI>
|
||||
void igl::opengl2::sort_triangles(
|
||||
const Eigen::PlainObjectBase<DerivedV> & V,
|
||||
const Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedFF> & FF,
|
||||
Eigen::PlainObjectBase<DerivedI> & I)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
// Put model, projection, and viewport matrices into double arrays
|
||||
Matrix4d MV;
|
||||
Matrix4d P;
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, MV.data());
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, P.data());
|
||||
if(V.cols() == 3)
|
||||
{
|
||||
Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime,4> hV;
|
||||
hV.resize(V.rows(),4);
|
||||
hV.block(0,0,V.rows(),V.cols()) = V;
|
||||
hV.col(3).setConstant(1);
|
||||
return igl::sort_triangles(hV,F,MV,P,FF,I);
|
||||
}else
|
||||
{
|
||||
return igl::sort_triangles(V,F,MV,P,FF,I);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedFF,
|
||||
typename DerivedI>
|
||||
void igl::opengl2::sort_triangles_slow(
|
||||
const Eigen::PlainObjectBase<DerivedV> & V,
|
||||
const Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedFF> & FF,
|
||||
Eigen::PlainObjectBase<DerivedI> & I)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
// Barycenter, centroid
|
||||
Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
|
||||
Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,3> BC;
|
||||
D.resize(F.rows(),3);
|
||||
barycenter(V,F,BC);
|
||||
for(int f = 0;f<F.rows();f++)
|
||||
{
|
||||
Eigen::Matrix<typename DerivedV::Scalar, 3,1> bc,pbc;
|
||||
bc = BC.row(f);
|
||||
project(bc,pbc);
|
||||
D(f) = pbc(2);
|
||||
}
|
||||
sort(D,1,false,sD,I);
|
||||
slice(F,I,1,FF);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::opengl2::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::opengl2::sort_triangles_slow<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user