Compare commits
260 Commits
temp-inter
...
HMD_viewpo
Author | SHA1 | Date | |
---|---|---|---|
![]() |
792f0aaad5 | ||
bc6f689448 | |||
6814b392eb | |||
![]() |
9e17c831eb | ||
![]() |
2d9f41b1bd | ||
![]() |
1a0b5c3a99 | ||
![]() |
dd2bdd2ca0 | ||
![]() |
d4dd0184a8 | ||
![]() |
a61b751972 | ||
![]() |
01acc0d59f | ||
![]() |
3113329f79 | ||
![]() |
a07ca22a99 | ||
![]() |
8437c6e28e | ||
![]() |
a993466b22 | ||
a21130f737 | |||
![]() |
0b4e2631d2 | ||
![]() |
623841e7df | ||
![]() |
b3cdca4a0a | ||
![]() |
511347ff30 | ||
![]() |
8e4b4881c8 | ||
![]() |
3c51b670c5 | ||
![]() |
c87925469b | ||
![]() |
2fa9fceba0 | ||
2cd6dfe86e | |||
f38dc5c06b | |||
66a20c9ad7 | |||
c68fabee47 | |||
e53d432787 | |||
355bbb1d49 | |||
1b81d776d7 | |||
ea85e2fad3 | |||
52e007dbb2 | |||
9327880109 | |||
7e4a96f0ab | |||
06e9f3304c | |||
9d1b98d383 | |||
![]() |
3d7ca99c89 | ||
![]() |
66952dabe8 | ||
![]() |
8081480a86 | ||
4deff6951d | |||
43a1310508 | |||
634067f442 | |||
![]() |
abe2669720 | ||
![]() |
cecbb727ac | ||
![]() |
08870e72bc | ||
![]() |
66026afd69 | ||
![]() |
fc0fb35df5 | ||
![]() |
96ef1beb58 | ||
![]() |
af3917049b | ||
![]() |
982c41b549 | ||
bed9bf1907 | |||
![]() |
5605db8611 | ||
![]() |
7015b229d1 | ||
a5d19a22b7 | |||
1d1ba540bb | |||
![]() |
edd74baa15 | ||
![]() |
20763919a1 | ||
![]() |
d5f0807c63 | ||
![]() |
6907aa26c6 | ||
![]() |
4950ce4cd9 | ||
![]() |
07706a28d0 | ||
![]() |
2f0d8e799a | ||
![]() |
b3c156927a | ||
284c7f72a1 | |||
![]() |
724a991b7f | ||
![]() |
3a79183097 | ||
![]() |
f705c53cfa | ||
![]() |
a8a93f000a | ||
![]() |
3ef07b29c5 | ||
![]() |
8f55592e77 | ||
![]() |
926b9ea918 | ||
![]() |
0261a18677 | ||
3e486c19ff | |||
22570c0ab4 | |||
![]() |
3fb0674a1a | ||
ef017ec9d0 | |||
3318e7bd13 | |||
0bbbeead7d | |||
68f931fd90 | |||
![]() |
f81ead6c38 | ||
![]() |
c8d1319452 | ||
![]() |
0c86cebeb2 | ||
![]() |
129955e34b | ||
![]() |
67847067b9 | ||
![]() |
6a696c5bb4 | ||
![]() |
1ea4d4362d | ||
![]() |
a757065875 | ||
![]() |
911fd31894 | ||
![]() |
585c5e72ab | ||
![]() |
d0000ef6fc | ||
![]() |
91d0198d0e | ||
![]() |
e2dd63eb55 | ||
![]() |
48b38797c6 | ||
![]() |
e06fa55a48 | ||
![]() |
d9428f7a03 | ||
![]() |
c2b72626bf | ||
![]() |
8bfc10ce66 | ||
![]() |
a29c325c83 | ||
![]() |
509945633b | ||
![]() |
fdb0d37bdf | ||
![]() |
ccf5de8a71 | ||
![]() |
9ce9540afd | ||
![]() |
fdd4c5a98d | ||
e2ccfdaa29 | |||
8e1cf5237f | |||
994795c1ed | |||
![]() |
54ed6f8918 | ||
![]() |
ce4f04f268 | ||
![]() |
e7670e9bb0 | ||
![]() |
46bc9bcbba | ||
![]() |
1a0d1064ee | ||
![]() |
bebd1fbcd8 | ||
459f922484 | |||
![]() |
913903af74 | ||
![]() |
1a1b51f329 | ||
![]() |
b7beb76211 | ||
![]() |
2d2d44ca71 | ||
![]() |
14b9e0a933 | ||
![]() |
6d52d7e32d | ||
![]() |
bf426bdf1e | ||
![]() |
a1562bbb53 | ||
![]() |
505b1fdcb2 | ||
![]() |
b95a7c0af3 | ||
![]() |
f8cfffec4f | ||
![]() |
17a7c6a140 | ||
![]() |
e4a82a1e39 | ||
![]() |
7a4138a5b9 | ||
![]() |
99a29209b4 | ||
![]() |
637ca57ce9 | ||
![]() |
9d9db8f748 | ||
![]() |
ed34f17604 | ||
![]() |
3db824b617 | ||
![]() |
24f4c98cc2 | ||
![]() |
c1846b18b1 | ||
![]() |
f40b22365d | ||
![]() |
ebc32889be | ||
![]() |
ddb2a36a4d | ||
![]() |
17cbaf5d16 | ||
![]() |
2ccdd0be51 | ||
![]() |
753dbee557 | ||
![]() |
495e99fbc1 | ||
![]() |
2924c09298 | ||
![]() |
3d9fca040b | ||
![]() |
122e479fe7 | ||
![]() |
d0fce1c992 | ||
![]() |
eb9f4d233c | ||
![]() |
e1b662f017 | ||
![]() |
a68db93fc2 | ||
![]() |
6e30e9b16d | ||
![]() |
7cf31cb048 | ||
![]() |
8f025c41e4 | ||
![]() |
28d4cdaffc | ||
![]() |
d90aec52ff | ||
3774a424ea | |||
![]() |
95074bcd12 | ||
![]() |
506dfd65eb | ||
![]() |
eebc41ec4f | ||
185619229c | |||
b99acd7338 | |||
![]() |
699df00847 | ||
![]() |
dbd5663c26 | ||
90746deeec | |||
![]() |
c2fe571634 | ||
![]() |
bf4fe3c84f | ||
![]() |
4c4333e06c | ||
![]() |
18f050f951 | ||
53bf3e1d84 | |||
![]() |
072f453448 | ||
![]() |
cc160fb0a2 | ||
b90f3b1982 | |||
![]() |
a32710fd90 | ||
![]() |
a742abfafb | ||
![]() |
deb3e28954 | ||
![]() |
077e3109c8 | ||
![]() |
4424a8e844 | ||
![]() |
6485c25c0e | ||
![]() |
8ec1bb0966 | ||
![]() |
1a3c402585 | ||
![]() |
088e381ae2 | ||
![]() |
21fc36fbc8 | ||
![]() |
d81b2309bc | ||
![]() |
16af40cc36 | ||
![]() |
691e8b135c | ||
![]() |
60645b4030 | ||
![]() |
30723504be | ||
![]() |
4bb2efcb6e | ||
![]() |
0c029b7f86 | ||
b189710cd8 | |||
![]() |
88879dfae1 | ||
![]() |
eec5ac5927 | ||
![]() |
bacadeb8c4 | ||
![]() |
85759e74ab | ||
![]() |
0b41972dca | ||
![]() |
c04031e94f | ||
![]() |
45397af24a | ||
![]() |
2f4148d833 | ||
![]() |
c8eb1c93af | ||
![]() |
8f9b30610b | ||
![]() |
410b681d1f | ||
![]() |
b6174113c9 | ||
![]() |
72e5ee8471 | ||
![]() |
c5fc10ba3f | ||
![]() |
03e8afdb8d | ||
![]() |
2d57a89629 | ||
![]() |
f83eba6011 | ||
![]() |
367b6f1646 | ||
c0ddaefb5d | |||
58568d1bd3 | |||
b811750153 | |||
![]() |
9f145cd1b4 | ||
![]() |
0751953efd | ||
ad502106e4 | |||
![]() |
9e1583a0a9 | ||
d8239304de | |||
![]() |
d04b6a7cda | ||
![]() |
49d9131ebd | ||
![]() |
599355304d | ||
![]() |
5a8e1c28c8 | ||
134be85218 | |||
3609e8868c | |||
![]() |
53d36ad280 | ||
12ee739cbc | |||
![]() |
e56fda407c | ||
![]() |
85cde2a444 | ||
![]() |
9c4e06fcc4 | ||
062d66156b | |||
b7ff6efaf2 | |||
![]() |
38c6437df7 | ||
53d1c4ed05 | |||
fcaf81cf2d | |||
![]() |
98535f578a | ||
![]() |
13d06fa38b | ||
![]() |
164a1af8cd | ||
f35c1a339d | |||
![]() |
a9d0ca72c6 | ||
![]() |
b0f91cc221 | ||
![]() |
c3b1c5d026 | ||
![]() |
1863ebcacc | ||
![]() |
5ff399d69a | ||
![]() |
30647c0d5c | ||
![]() |
5ec1249769 | ||
![]() |
a3d4644996 | ||
163e978be1 | |||
![]() |
4f38d44eb2 | ||
![]() |
cde072b618 | ||
713829c8e4 | |||
e806f478e5 | |||
![]() |
5b8c1da845 | ||
![]() |
b8d2c0da47 | ||
![]() |
c5a75b8647 | ||
![]() |
409154f1f8 | ||
![]() |
994e0b04d9 | ||
![]() |
e4bc3bac37 | ||
![]() |
fe520b7688 | ||
d737b41a47 | |||
![]() |
759be70ab4 | ||
![]() |
8b701bb913 | ||
![]() |
764a878938 | ||
![]() |
408cbe918b | ||
![]() |
57424a2401 |
@@ -371,6 +371,13 @@ if(WIN32)
|
||||
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
|
||||
endif()
|
||||
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF})
|
||||
|
||||
# HMD - actually not really input, there's also some other stuff for it
|
||||
option(WITH_INPUT_HMD "Enable HMD support in Blender (Head Mounted Displays for VR support)" ON)
|
||||
option(WITH_OPENHMD "Enable OpenHMD driver library" ON)
|
||||
option(WITH_OPENHMD_DYNLOAD "Dynamically load OpenHMD dependencies at runtime" OFF)
|
||||
mark_as_advanced(WITH_OPENHMD_DYNLOAD)
|
||||
|
||||
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
|
||||
@@ -709,6 +716,15 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
|
||||
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_HMD AND NOT WITH_OPENHMD)
|
||||
message(WARNING "WITH_INPUT_HMD is enabled, but OpenHMD driver (WITH_OPENHMD) is disabled. "
|
||||
"Only a limited set of HMD features will be available.")
|
||||
endif()
|
||||
|
||||
if(WITH_OPENHMD AND NOT WITH_INPUT_HMD)
|
||||
message(FATAL_ERROR "WITH_OPENHMD requires WITH_INPUT_HMD")
|
||||
endif()
|
||||
|
||||
|
||||
# may as well build python module without a UI
|
||||
if(WITH_PYTHON_MODULE)
|
||||
|
@@ -30,13 +30,13 @@ with-all,with-opencollada,\
|
||||
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
|
||||
force-all,force-python,force-numpy,force-boost,\
|
||||
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
|
||||
force-ffmpeg,force-opencollada,force-alembic,\
|
||||
force-ffmpeg,force-opencollada,force-alembic,force-hidapi\
|
||||
build-all,build-python,build-numpy,build-boost,\
|
||||
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
|
||||
build-ffmpeg,build-opencollada,build-alembic,\
|
||||
build-ffmpeg,build-opencollada,build-alembic,build-hidapi\
|
||||
skip-python,skip-numpy,skip-boost,\
|
||||
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
|
||||
skip-ffmpeg,skip-opencollada,skip-alembic \
|
||||
skip-ffmpeg,skip-opencollada,skip-alembic,skip-hidapi \
|
||||
-- "$@" \
|
||||
)
|
||||
|
||||
@@ -182,6 +182,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--build-ffmpeg
|
||||
Force the build of FFMpeg.
|
||||
|
||||
--build-hidapi
|
||||
Force the build of hidapi.
|
||||
|
||||
Note about the --build-foo options:
|
||||
* They force the script to prefer building dependencies rather than using available packages.
|
||||
This may make things simpler and allow working around some distribution bugs, but on the other hand it will
|
||||
@@ -234,6 +237,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--force-ffmpeg
|
||||
Force the rebuild of FFMpeg.
|
||||
|
||||
--force-hidapi
|
||||
Force the rebuild of hidapi.
|
||||
|
||||
Note about the --force-foo options:
|
||||
* They obviously only have an effect if those libraries are built by this script
|
||||
(i.e. if there is no available and satisfactory package)!
|
||||
@@ -277,7 +283,10 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
Unconditionally skip OpenCOLLADA installation/building.
|
||||
|
||||
--skip-ffmpeg
|
||||
Unconditionally skip FFMpeg installation/building.\""
|
||||
Unconditionally skip FFMpeg installation/building.
|
||||
|
||||
--skip-hidapi
|
||||
Unconditionally skip hidapi installation/building.\""
|
||||
|
||||
##### Main Vars #####
|
||||
|
||||
@@ -399,6 +408,12 @@ MP3LAME_DEV=""
|
||||
OPENJPEG_USE=false
|
||||
OPENJPEG_DEV=""
|
||||
|
||||
HIDAPI_VERSION="0.8.0"
|
||||
HIDAPI_VERSION_MIN="0.8.0"
|
||||
HIDAPI_FORCE_BUILD=false
|
||||
HIDAPI_FORCE_REBUILD=false
|
||||
HIDAPI_SKIP=false
|
||||
|
||||
# Whether to use system GLEW or not (OpenSubDiv needs recent glew to work).
|
||||
NO_SYSTEM_GLEW=false
|
||||
|
||||
@@ -597,6 +612,9 @@ while true; do
|
||||
--build-alembic)
|
||||
ALEMBIC_FORCE_BUILD=true; shift; continue
|
||||
;;
|
||||
--build-hidapi)
|
||||
HIDAPI_FORCE_BUILD=true; shift; continue
|
||||
;;
|
||||
--force-all)
|
||||
PYTHON_FORCE_REBUILD=true
|
||||
NUMPY_FORCE_REBUILD=true
|
||||
@@ -611,6 +629,7 @@ while true; do
|
||||
OPENCOLLADA_FORCE_REBUILD=true
|
||||
FFMPEG_FORCE_REBUILD=true
|
||||
ALEMBIC_FORCE_REBUILD=true
|
||||
HIDAPI_FORCE_REBUILD=true
|
||||
shift; continue
|
||||
;;
|
||||
--force-python)
|
||||
@@ -654,6 +673,9 @@ while true; do
|
||||
--force-alembic)
|
||||
ALEMBIC_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--force-hidapi)
|
||||
HIDAPI_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--skip-python)
|
||||
PYTHON_SKIP=true; shift; continue
|
||||
;;
|
||||
@@ -693,6 +715,9 @@ while true; do
|
||||
--skip-alembic)
|
||||
ALEMBIC_SKIP=true; shift; continue
|
||||
;;
|
||||
--skip-hidapi)
|
||||
HIDAPI_SKIP=true; shift; continue
|
||||
;;
|
||||
--)
|
||||
# no more arguments to parse
|
||||
break
|
||||
@@ -791,6 +816,8 @@ OPENCOLLADA_REPO_BRANCH="master"
|
||||
|
||||
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
|
||||
|
||||
HIDAPI_SOURCE=( "https://github.com/signal11/hidapi/archive/hidapi-0.8.0-rc1.tar.gz" )
|
||||
|
||||
CXXFLAGS_BACK=$CXXFLAGS
|
||||
if [ "$USE_CXX11" = true ]; then
|
||||
WARNING "You are trying to use c++11, this *should* go smoothely with any very recent distribution
|
||||
@@ -839,7 +866,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
|
||||
* [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID).
|
||||
* [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE).
|
||||
* [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID).
|
||||
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).\""
|
||||
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).
|
||||
* [HIDAPI $HIDAPI_VERSION] (from $HIDAPI_SOURCE).\""
|
||||
|
||||
if [ "$DO_SHOW_DEPS" = true ]; then
|
||||
PRINT ""
|
||||
@@ -2511,6 +2539,75 @@ compile_FFmpeg() {
|
||||
fi
|
||||
}
|
||||
|
||||
#### Build HIDAPI ####
|
||||
_init_hidapi() {
|
||||
_src=$SRC/hidapi-$HIDAPI_VERSION
|
||||
_inst=$INST/hidapi-$HIDAPI_VERSION
|
||||
_inst_shortcut=$INST/hidapi
|
||||
}
|
||||
|
||||
clean_hidapi() {
|
||||
_init_hidapi
|
||||
_clean
|
||||
}
|
||||
|
||||
compile_hidapi() {
|
||||
if [ "$NO_BUILD" = true ]; then
|
||||
WARNING "--no-build enabled, HIDAPI will not be compiled!"
|
||||
return
|
||||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
hidapi_magic=1
|
||||
_init_hidapi
|
||||
|
||||
# Clean install if needed!
|
||||
magic_compile_check hidapi-$HIDAPI_VERSION $hidapi_magic
|
||||
if [ $? -eq 1 -o "$HIDAPI_FORCE_REBUILD" = true ]; then
|
||||
clean_hidapi
|
||||
fi
|
||||
|
||||
if [ ! -d $_inst ]; then
|
||||
INFO "Building hidapi-$HIDAPI_VERSION"
|
||||
|
||||
prepare_opt
|
||||
|
||||
if [ ! -d $_src -o true ]; then
|
||||
mkdir -p $SRC
|
||||
download HIDAPI_SOURCE[@] "$_src.tar.gz"
|
||||
|
||||
INFO "Unpacking hidapi-$HIDAPI_VERSION"
|
||||
tar -C $SRC --transform "s,(/?)hidapi-[^/]*(.*),\1hidapi-$HIDAPI_VERSION\2,x" -xf $_src.tar.gz
|
||||
fi
|
||||
|
||||
cd $_src
|
||||
|
||||
./bootstrap
|
||||
./configure --prefix=$_inst
|
||||
|
||||
make -j$THREADS install
|
||||
make clean
|
||||
|
||||
if [ -d $_inst ]; then
|
||||
_create_inst_shortcut
|
||||
else
|
||||
ERROR "hidapi-$HIDAPI_VERSION failed to compile, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
magic_compile_set hidapi-$HIDAPI_VERSION $hidapi_magic
|
||||
|
||||
cd $CWD
|
||||
INFO "Done compiling hidapi-$HIDAPI_VERSION!"
|
||||
else
|
||||
INFO "Own hidapi-$HIDAPI_VERSION is up to date, nothing to do!"
|
||||
INFO "If you want to force rebuild of this lib, use the --force-hidapi option."
|
||||
fi
|
||||
|
||||
run_ldconfig "hidapi"
|
||||
}
|
||||
|
||||
|
||||
|
||||
#### Install on DEB-like ####
|
||||
get_package_version_DEB() {
|
||||
@@ -2982,6 +3079,34 @@ install_DEB() {
|
||||
compile_FFmpeg
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
PRINT ""
|
||||
_do_compile_hidapi=false
|
||||
if [ "$HIDAPI_SKIP" = true ]; then
|
||||
WARNING "Skipping hidapi installation, as requested..."
|
||||
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced hidapi building, as requested..."
|
||||
_do_compile_hidapi=true
|
||||
else
|
||||
check_package_DEB libhidapi-dev
|
||||
if [ $? -eq 0 ]; then
|
||||
check_package_version_ge_DEB libhidapi-dev $HIDAPI_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_DEB libhidapi-dev
|
||||
clean_hidapi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_do_compile_hidapi" = true ]; then
|
||||
install_packages_DEB libudev-dev libusb-1.0-0-dev
|
||||
compile_hidapi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -3523,6 +3648,33 @@ install_RPM() {
|
||||
compile_FFmpeg
|
||||
fi
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
_do_compile_hidapi=false
|
||||
if [ "$HIDAPI_SKIP" = true ]; then
|
||||
WARNING "Skipping hidapi installation, as requested..."
|
||||
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced hidapi building, as requested..."
|
||||
_do_compile_hidapi=true
|
||||
else
|
||||
check_package_RPM hidapi-devel
|
||||
if [ $? -eq 0 ]; then
|
||||
check_package_version_ge_RPM hidapi-devel $HIDAPI_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_RPM hidapi-devel
|
||||
clean_hidapi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_do_compile_hidapi" = true ]; then
|
||||
install_packages_RPM libusbx-devel # No libudev in fedora?
|
||||
compile_hidapi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -3948,6 +4100,33 @@ install_ARCH() {
|
||||
compile_FFmpeg
|
||||
fi
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
_do_compile_hidapi=false
|
||||
if [ "$HIDAPI_SKIP" = true ]; then
|
||||
WARNING "Skipping hidapi installation, as requested..."
|
||||
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced hidapi building, as requested..."
|
||||
_do_compile_hidapi=true
|
||||
else
|
||||
check_package_ARCH hidapi
|
||||
if [ $? -eq 0 ]; then
|
||||
check_package_version_ge_ARCH hidapi $HIDAPI_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_ARCH hidapi
|
||||
clean_hidapi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
else
|
||||
_do_compile_hidapi=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_do_compile_hidapi" = true ]; then
|
||||
install_packages_ARCH libusb # No libudev in arch?
|
||||
compile_hidapi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -4111,6 +4290,16 @@ install_OTHER() {
|
||||
INFO "Forced FFMpeg building, as requested..."
|
||||
compile_FFmpeg
|
||||
fi
|
||||
|
||||
|
||||
PRINT ""
|
||||
_do_compile_hidapi=false
|
||||
if [ "$HIDAPI_SKIP" = true ]; then
|
||||
WARNING "Skipping hidapi installation, as requested..."
|
||||
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced hidapi building, as requested..."
|
||||
compile_hidapi
|
||||
fi
|
||||
}
|
||||
|
||||
#### Printing User Info ####
|
||||
@@ -4192,7 +4381,7 @@ print_info() {
|
||||
|
||||
_buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*"
|
||||
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
|
||||
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
|
||||
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *OPENHMD* -U *HIDAPI*"
|
||||
|
||||
if [ "$USE_CXX11" = true ]; then
|
||||
_1="-D WITH_CXX11=ON"
|
||||
@@ -4334,6 +4523,17 @@ print_info() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$HIDAPI_SKIP" = false ]; then
|
||||
_1="-D WITH_OPENHMD=ON"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
if [ -d $INST/hidapi ]; then
|
||||
_1="-D HIDAPI_ROOT_DIR=$INST/hidapi"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
PRINT "Or even simpler, just run (in your blender-source dir):"
|
||||
PRINT " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
|
||||
|
@@ -144,5 +144,14 @@ set(OPENVDB_LIBRARY
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
|
||||
# OpenHMD
|
||||
if(GLIBC EQUAL "2.19")
|
||||
set(HIDAPI_LIBRARY
|
||||
/usr/lib${MULTILIB}/libhidapi-hidraw.a
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
set(WITH_OPENHMD_DYNLOAD ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
# Additional linking libraries
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-lrt -static-libstdc++" CACHE STRING "" FORCE)
|
||||
|
71
build_files/cmake/Modules/FindHIDAPI.cmake
Normal file
71
build_files/cmake/Modules/FindHIDAPI.cmake
Normal file
@@ -0,0 +1,71 @@
|
||||
# - Find HIDAPI library from http://www.signal11.us/oss/hidapi/
|
||||
# Find the native HIDAPI includes and library
|
||||
# This module defines
|
||||
# HIDAPI_INCLUDE_DIRS, where to find hidapi.h, Set when
|
||||
# HIDAPI_INCLUDE_DIR is found.
|
||||
# HIDAPI_LIBRARIES, libraries to link against to use HIDAPI.
|
||||
# HIDAPI_ROOT_DIR, The base directory to search for HIDAPI.
|
||||
# This can also be an environment variable.
|
||||
# HIDAPI_FOUND, If false, do not try to use HIDAPI.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
# HIDAPI_LIBRARY, where to find the HIDAPI library.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2016 Blender Foundation.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
|
||||
# If HIDAPI_ROOT_DIR was defined in the environment, use it.
|
||||
IF(NOT HIDAPI_ROOT_DIR AND NOT $ENV{HIDAPI_ROOT_DIR} STREQUAL "")
|
||||
SET(HIDAPI_ROOT_DIR $ENV{HIDAPI_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_hidapi_SEARCH_DIRS
|
||||
${HIDAPI_ROOT_DIR}
|
||||
/usr/local
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt/lib/hidapi
|
||||
)
|
||||
|
||||
FIND_PATH(HIDAPI_INCLUDE_DIR
|
||||
NAMES
|
||||
hidapi.h
|
||||
HINTS
|
||||
${_hidapi_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include/hidapi
|
||||
)
|
||||
|
||||
FIND_LIBRARY(HIDAPI_LIBRARY
|
||||
NAMES
|
||||
hidapi hidapi-libusb
|
||||
HINTS
|
||||
${_hidapi_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set HIDAPI_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HIDAPI DEFAULT_MSG
|
||||
HIDAPI_LIBRARY HIDAPI_INCLUDE_DIR)
|
||||
|
||||
IF(HIDAPI_FOUND)
|
||||
SET(HIDAPI_LIBRARIES ${HIDAPI_LIBRARY})
|
||||
SET(HIDAPI_INCLUDE_DIRS ${HIDAPI_INCLUDE_DIR})
|
||||
ENDIF(HIDAPI_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
HIDAPI_INCLUDE_DIR
|
||||
HIDAPI_LIBRARY
|
||||
)
|
@@ -492,6 +492,10 @@ function(setup_liblinks
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENHMD)
|
||||
target_link_libraries(${target} ${OPENHMD_LIBRARIES} ${HIDAPI_LIBRARY})
|
||||
endif()
|
||||
|
||||
# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
|
||||
if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
|
||||
target_link_libraries(${target} "extern_clew")
|
||||
@@ -501,6 +505,9 @@ function(setup_liblinks
|
||||
target_link_libraries(${target} ${CUDA_CUDA_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
if(WITH_OPENHMD AND WITH_OPENHMD_DYNLOAD)
|
||||
target_link_libraries(${target} "extern_udew")
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
${target}
|
||||
@@ -707,6 +714,10 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_quicktime)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENHMD)
|
||||
list(APPEND BLENDER_SORTED_LIBS extern_openhmd)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
list(APPEND BLENDER_SORTED_LIBS extern_carve)
|
||||
endif()
|
||||
|
@@ -66,7 +66,7 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32
|
||||
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp
|
||||
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp setupapi
|
||||
)
|
||||
|
||||
if(WITH_INPUT_IME)
|
||||
|
8
extern/CMakeLists.txt
vendored
8
extern/CMakeLists.txt
vendored
@@ -86,6 +86,10 @@ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENHMD AND WITH_OPENHMD_DYNLOAD)
|
||||
add_subdirectory(udew)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(carve)
|
||||
endif()
|
||||
@@ -111,3 +115,7 @@ endif()
|
||||
if(WITH_SDL AND WITH_SDL_DYNLOAD)
|
||||
add_subdirectory(sdlew)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENHMD)
|
||||
add_subdirectory(openhmd)
|
||||
endif()
|
||||
|
111
extern/openhmd/CMakeLists.txt
vendored
Normal file
111
extern/openhmd/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
src
|
||||
include
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
set(SRC
|
||||
src/openhmd.c
|
||||
src/platform-win32.c
|
||||
src/drv_dummy/dummy.c
|
||||
src/omath.c
|
||||
src/platform-posix.c
|
||||
src/fusion.c
|
||||
src/queue.c
|
||||
src/shaders.c
|
||||
)
|
||||
|
||||
# TODO: Either remove this or move to main CMakeLists.txt
|
||||
OPTION(OPENHMD_DRIVER_OCULUS_RIFT "Oculus Rift DK1, DK2 and CV1" ON)
|
||||
OPTION(OPENHMD_DRIVER_DEEPOON "Deepoon E2" ON)
|
||||
OPTION(OPENHMD_DRIVER_PSVR "Sony PSVR" ON)
|
||||
OPTION(OPENHMD_DRIVER_HTC_VIVE "HTC Vive" ON)
|
||||
OPTION(OPENHMD_DRIVER_EXTERNAL "External sensor driver" OFF)
|
||||
OPTION(OPENHMD_DRIVER_ANDROID "General Android driver" OFF)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-DOHMD_STATIC)
|
||||
endif(MSVC)
|
||||
|
||||
|
||||
if(OPENHMD_DRIVER_OCULUS_RIFT)
|
||||
list(APPEND SRC
|
||||
src/drv_oculus_rift/rift.c
|
||||
src/drv_oculus_rift/packet.c
|
||||
)
|
||||
add_definitions(-DDRIVER_OCULUS_RIFT)
|
||||
|
||||
find_package(HIDAPI REQUIRED)
|
||||
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(OPENHMD_DRIVER_DEEPOON)
|
||||
list(APPEND SRC
|
||||
src/drv_deepoon/deepoon.c
|
||||
src/drv_deepoon/packet.c
|
||||
)
|
||||
add_definitions(-DDRIVER_DEEPOON)
|
||||
|
||||
find_package(HIDAPI REQUIRED)
|
||||
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(OPENHMD_DRIVER_PSVR)
|
||||
list(APPEND SRC
|
||||
src/drv_psvr/psvr.c
|
||||
src/drv_psvr/packet.c
|
||||
)
|
||||
add_definitions(-DDRIVER_PSVR)
|
||||
|
||||
find_package(HIDAPI REQUIRED)
|
||||
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(OPENHMD_DRIVER_HTC_VIVE)
|
||||
list(APPEND SRC
|
||||
src/drv_htc_vive/vive.c
|
||||
src/drv_htc_vive/packet.c
|
||||
)
|
||||
add_definitions(-DDRIVER_HTC_VIVE)
|
||||
|
||||
find_package(HIDAPI REQUIRED)
|
||||
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(OPENHMD_DRIVER_EXTERNAL)
|
||||
list(APPEND SRC
|
||||
src/drv_external/external.c
|
||||
)
|
||||
add_definitions(-DDRIVER_EXTERNAL)
|
||||
endif()
|
||||
|
||||
if(OPENHMD_DRIVER_ANDROID)
|
||||
list(APPEND SRC
|
||||
src/drv_android/android.c
|
||||
)
|
||||
add_definitions(-DDRIVER_ANDROID)
|
||||
endif()
|
||||
|
||||
blender_add_lib(extern_openhmd "${SRC}" "${INC}" "${INC_SYS}")
|
23
extern/openhmd/LICENSE
vendored
Normal file
23
extern/openhmd/LICENSE
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
9
extern/openhmd/README.md
vendored
Normal file
9
extern/openhmd/README.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# OpenHMD
|
||||
This project aims to provide a Free and Open Source API and drivers for immersive technology, such as head mounted displays with built in head tracking.
|
||||
|
||||
# License
|
||||
OpenHMD is released under the permissive Boost Software License (see LICENSE for more information), to make sure it can be linked and distributed with both free and non-free software. While it doesn't require contribution from the users, it is still very appreciated.
|
||||
|
||||
# Implemented and maintained by TheOnlyJoey (Joey Ferwerda), contact info@thorwork.org if anything goes wrong
|
||||
|
||||
|
390
extern/openhmd/include/openhmd.h
vendored
Normal file
390
extern/openhmd/include/openhmd.h
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file openhmd.h
|
||||
* Main header for OpenHMD public API.
|
||||
**/
|
||||
|
||||
#ifndef OPENHMD_H
|
||||
#define OPENHMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef DLL_EXPORT
|
||||
#define OHMD_APIENTRY __cdecl
|
||||
#define OHMD_APIENTRYDLL __declspec( dllexport )
|
||||
#else
|
||||
#ifdef OHMD_STATIC
|
||||
#define OHMD_APIENTRY __cdecl
|
||||
#define OHMD_APIENTRYDLL
|
||||
#else
|
||||
#define OHMD_APIENTRY __cdecl
|
||||
#define OHMD_APIENTRYDLL __declspec( dllimport )
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define OHMD_APIENTRY
|
||||
#define OHMD_APIENTRYDLL
|
||||
#endif
|
||||
|
||||
/** Maximum length of a string, including termination, in OpenHMD. */
|
||||
#define OHMD_STR_SIZE 256
|
||||
|
||||
/** Return status codes, used for all functions that can return an error. */
|
||||
typedef enum {
|
||||
OHMD_S_OK = 0,
|
||||
OHMD_S_UNKNOWN_ERROR = -1,
|
||||
OHMD_S_INVALID_PARAMETER = -2,
|
||||
OHMD_S_UNSUPPORTED = -3,
|
||||
OHMD_S_INVALID_OPERATION = -4,
|
||||
|
||||
/** OHMD_S_USER_RESERVED and below can be used for user purposes, such as errors within ohmd wrappers, etc. */
|
||||
OHMD_S_USER_RESERVED = -16384,
|
||||
} ohmd_status;
|
||||
|
||||
/** A collection of string value information types, used for getting information with ohmd_list_gets(). */
|
||||
typedef enum {
|
||||
OHMD_VENDOR = 0,
|
||||
OHMD_PRODUCT = 1,
|
||||
OHMD_PATH = 2,
|
||||
} ohmd_string_value;
|
||||
|
||||
/** A collection of string descriptions, used for getting strings with ohmd_gets(). */
|
||||
typedef enum {
|
||||
OHMD_GLSL_DISTORTION_VERT_SRC = 0,
|
||||
OHMD_GLSL_DISTORTION_FRAG_SRC = 1,
|
||||
} ohmd_string_description;
|
||||
|
||||
/** A collection of float value information types, used for getting and setting information with
|
||||
ohmd_device_getf() and ohmd_device_setf(). */
|
||||
typedef enum {
|
||||
/** float[4] (get): Absolute rotation of the device, in space, as a quaternion (x, y, z, w). */
|
||||
OHMD_ROTATION_QUAT = 1,
|
||||
|
||||
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
|
||||
left eye of the HMD. */
|
||||
OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX = 2,
|
||||
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
|
||||
right eye of the HMD. */
|
||||
OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX = 3,
|
||||
|
||||
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
|
||||
left eye of the HMD. */
|
||||
OHMD_LEFT_EYE_GL_PROJECTION_MATRIX = 4,
|
||||
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
|
||||
right eye of the HMD. */
|
||||
OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX = 5,
|
||||
|
||||
/** float[3] (get): A 3-D vector representing the absolute position of the device, in space. */
|
||||
OHMD_POSITION_VECTOR = 6,
|
||||
|
||||
/** float[1] (get): Physical width of the device screen in metres. */
|
||||
OHMD_SCREEN_HORIZONTAL_SIZE = 7,
|
||||
/** float[1] (get): Physical height of the device screen in metres. */
|
||||
OHMD_SCREEN_VERTICAL_SIZE = 8,
|
||||
|
||||
/** float[1] (get): Physical separation of the device lenses in metres. */
|
||||
OHMD_LENS_HORIZONTAL_SEPARATION = 9,
|
||||
/** float[1] (get): Physical vertical position of the lenses in metres. */
|
||||
OHMD_LENS_VERTICAL_POSITION = 10,
|
||||
|
||||
/** float[1] (get): Physical field of view for the left eye in degrees. */
|
||||
OHMD_LEFT_EYE_FOV = 11,
|
||||
/** float[1] (get): Physical display aspect ratio for the left eye screen. */
|
||||
OHMD_LEFT_EYE_ASPECT_RATIO = 12,
|
||||
/** float[1] (get): Physical field of view for the left right in degrees. */
|
||||
OHMD_RIGHT_EYE_FOV = 13,
|
||||
/** float[1] (get): Physical display aspect ratio for the right eye screen. */
|
||||
OHMD_RIGHT_EYE_ASPECT_RATIO = 14,
|
||||
|
||||
/** float[1] (get, set): Physical interpupillary distance of the user in metres. */
|
||||
OHMD_EYE_IPD = 15,
|
||||
|
||||
/** float[1] (get, set): Z-far value for the projection matrix calculations (i.e. drawing distance). */
|
||||
OHMD_PROJECTION_ZFAR = 16,
|
||||
/** float[1] (get, set): Z-near value for the projection matrix calculations (i.e. close clipping distance). */
|
||||
OHMD_PROJECTION_ZNEAR = 17,
|
||||
|
||||
/** float[6] (get): Device specific distortion value. */
|
||||
OHMD_DISTORTION_K = 18,
|
||||
|
||||
/**
|
||||
* float[10] (set): Perform sensor fusion on values from external sensors.
|
||||
*
|
||||
* Values are: dt (time since last update in seconds) X, Y, Z gyro, X, Y, Z accelerometer and X, Y, Z magnetometer.
|
||||
**/
|
||||
OHMD_EXTERNAL_SENSOR_FUSION = 19,
|
||||
|
||||
/** float[4] (get): Universal shader distortion coefficients (PanoTools model <a,b,c,d>. */
|
||||
OHMD_UNIVERSAL_DISTORTION_K = 20,
|
||||
|
||||
/** float[3] (get): Universal shader aberration coefficients (post warp scaling <r,g,b>. */
|
||||
OHMD_UNIVERSAL_ABERRATION_K = 21,
|
||||
|
||||
} ohmd_float_value;
|
||||
|
||||
/** A collection of int value information types used for getting information with ohmd_device_geti(). */
|
||||
typedef enum {
|
||||
/** int[1] (get): Physical horizontal resolution of the device screen. */
|
||||
OHMD_SCREEN_HORIZONTAL_RESOLUTION = 0,
|
||||
/** int[1] (get): Physical vertical resolution of the device screen. */
|
||||
OHMD_SCREEN_VERTICAL_RESOLUTION = 1,
|
||||
|
||||
/** int[1] (get): Get number of events waiting in digital input event queue. */
|
||||
OHMD_BUTTON_EVENT_COUNT = 2,
|
||||
/** int[1] (get): Get if the there was an overflow in the event queue causing events to be dropped. */
|
||||
OHMD_BUTTON_EVENT_OVERFLOW = 3,
|
||||
/** int[1] (get): Get the number of physical digital input buttons on the device. */
|
||||
OHMD_BUTTON_COUNT = 4,
|
||||
/** int[2] (get): Performs an event pop action. Format: [button_index, button_state], where button_state is either OHMD_BUTTON_DOWN or OHMD_BUTTON_UP */
|
||||
OHMD_BUTTON_POP_EVENT = 5,
|
||||
} ohmd_int_value;
|
||||
|
||||
/** A collection of data information types used for setting information with ohmd_set_data(). */
|
||||
typedef enum {
|
||||
/** void* (set): Set void* data for use in the internal drivers. */
|
||||
OHMD_DRIVER_DATA = 0,
|
||||
/**
|
||||
* ohmd_device_properties* (set):
|
||||
* Set the device properties based on the ohmd_device_properties struct for use in the internal drivers.
|
||||
*
|
||||
* This can be used to fill in information about the device internally, such as Android, or for setting profiles.
|
||||
**/
|
||||
OHMD_DRIVER_PROPERTIES = 1,
|
||||
} ohmd_data_value;
|
||||
|
||||
typedef enum {
|
||||
/** int[1] (set, default: 1): Set this to 0 to prevent OpenHMD from creating background threads to do automatic device ticking.
|
||||
Call ohmd_update(); must be called frequently, at least 10 times per second, if the background threads are disabled. */
|
||||
OHMD_IDS_AUTOMATIC_UPDATE = 0,
|
||||
} ohmd_int_settings;
|
||||
|
||||
/** Button states for digital input events. */
|
||||
typedef enum {
|
||||
/** Button was pressed. */
|
||||
OHMD_BUTTON_DOWN = 0,
|
||||
/** Button was released. */
|
||||
OHMD_BUTTON_UP = 1
|
||||
} ohmd_button_state;
|
||||
|
||||
/** An opaque pointer to a context structure. */
|
||||
typedef struct ohmd_context ohmd_context;
|
||||
|
||||
/** An opaque pointer to a structure representing a device, such as an HMD. */
|
||||
typedef struct ohmd_device ohmd_device;
|
||||
|
||||
/** An opaque pointer to a structure representing arguments for a device. */
|
||||
typedef struct ohmd_device_settings ohmd_device_settings;
|
||||
|
||||
/**
|
||||
* Create an OpenHMD context.
|
||||
*
|
||||
* @return a pointer to an allocated ohmd_context on success or NULL if it fails.
|
||||
**/
|
||||
OHMD_APIENTRYDLL ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void);
|
||||
|
||||
/**
|
||||
* Destroy an OpenHMD context.
|
||||
*
|
||||
* ohmd_ctx_destroy de-initializes and de-allocates an OpenHMD context allocated with ohmd_ctx_create.
|
||||
* All devices associated with the context are automatically closed.
|
||||
*
|
||||
* @param ctx The context to destroy.
|
||||
**/
|
||||
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_destroy(ohmd_context* ctx);
|
||||
|
||||
/**
|
||||
* Get the last error as a human readable string.
|
||||
*
|
||||
* If a function taking a context as an argument (ohmd_context "methods") returns non-successfully,
|
||||
* a human readable error message describing what went wrong can be retrieved with this function.
|
||||
*
|
||||
* @param ctx The context to retrieve the error message from.
|
||||
* @return a pointer to the error message.
|
||||
**/
|
||||
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_ctx_get_error(ohmd_context* ctx);
|
||||
|
||||
/**
|
||||
* Update a context.
|
||||
*
|
||||
* Update the values for the devices handled by a context.
|
||||
*
|
||||
* If background threads are disabled, this performs tasks like pumping events from the device. The exact details
|
||||
* are up to the driver but try to call it quite frequently.
|
||||
* Once per frame in a "game loop" should be sufficient.
|
||||
* If OpenHMD is handled in a background thread in your program, calling ohmd_ctx_update and then sleeping for 10-20 ms
|
||||
* is recommended.
|
||||
*
|
||||
* @param ctx The context that needs updating.
|
||||
**/
|
||||
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx);
|
||||
|
||||
/**
|
||||
* Probe for devices.
|
||||
*
|
||||
* Probes for and enumerates supported devices attached to the system.
|
||||
*
|
||||
* @param ctx A context with no currently open devices.
|
||||
* @return the number of devices found on the system.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx);
|
||||
|
||||
/**
|
||||
* Get string from openhmd.
|
||||
*
|
||||
* Gets a string from OpenHMD. This is where non-device specific strings reside.
|
||||
* This is where the distortion shader sources can be retrieved.
|
||||
*
|
||||
* @param type The name of the string to fetch. One of OHMD_GLSL_DISTORTION_FRAG_SRC, and OHMD_GLSL_DISTORTION_FRAG_SRC.
|
||||
* @return a string with a human readable device name.
|
||||
**/
|
||||
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type);
|
||||
|
||||
/**
|
||||
* Get device description from enumeration list index.
|
||||
*
|
||||
* Gets a human readable device description string from a zero indexed enumeration index
|
||||
* between 0 and (max - 1), where max is the number ohmd_ctx_probe returned
|
||||
* (i.e. if ohmd_ctx_probe returns 3, valid indices are 0, 1 and 2).
|
||||
* The function can return three types of data. The vendor name, the product name and
|
||||
* a driver specific path where the device is attached.
|
||||
*
|
||||
* ohmd_ctx_probe must be called before calling ohmd_list_gets.
|
||||
*
|
||||
* @param ctx A (probed) context.
|
||||
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
|
||||
* @param type The type of data to fetch. One of OHMD_VENDOR, OHMD_PRODUCT and OHMD_PATH.
|
||||
* @return a string with a human readable device name.
|
||||
**/
|
||||
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int index, ohmd_string_value type);
|
||||
|
||||
/**
|
||||
* Open a device.
|
||||
*
|
||||
* Opens a device from a zero indexed enumeration index between 0 and (max - 1)
|
||||
* where max is the number ohmd_ctx_probe returned (i.e. if ohmd_ctx_probe returns 3,
|
||||
* valid indices are 0, 1 and 2).
|
||||
*
|
||||
* ohmd_ctx_probe must be called before calling ohmd_list_open_device.
|
||||
*
|
||||
* @param ctx A (probed) context.
|
||||
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
|
||||
* @return a pointer to an ohmd_device, which represents a hardware device, such as an HMD.
|
||||
**/
|
||||
OHMD_APIENTRYDLL ohmd_device* OHMD_APIENTRY ohmd_list_open_device(ohmd_context* ctx, int index);
|
||||
|
||||
/**
|
||||
* Open a device with additional settings provided.
|
||||
*
|
||||
* Opens a device from a zero indexed enumeration index between 0 and (max - 1)
|
||||
* where max is the number ohmd_ctx_probe returned (i.e. if ohmd_ctx_probe returns 3,
|
||||
* valid indices are 0, 1 and 2).
|
||||
*
|
||||
* ohmd_ctx_probe must be called before calling ohmd_list_open_device.
|
||||
*
|
||||
* @param ctx A (probed) context.
|
||||
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
|
||||
* @param settings A pointer to a device settings struct.
|
||||
* @return a pointer to an ohmd_device, which represents a hardware device, such as an HMD.
|
||||
**/
|
||||
OHMD_APIENTRYDLL ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index, ohmd_device_settings* settings);
|
||||
|
||||
/**
|
||||
* Specify int settings in a device settings struct.
|
||||
*
|
||||
* @param settings The device settings struct to set values to.
|
||||
* @param key The specefic setting you wish to set.
|
||||
* @param value A pointer to an int or int array (containing the expected number of elements) with the value(s) you wish to set.
|
||||
**/
|
||||
OHMD_APIENTRYDLL ohmd_status OHMD_APIENTRY ohmd_device_settings_seti(ohmd_device_settings* settings, ohmd_int_settings key, const int* val);
|
||||
|
||||
/**
|
||||
* Create a device settings instance.
|
||||
*
|
||||
* @param ctx A pointer to a valid ohmd_context.
|
||||
* @return a pointer to an allocated ohmd_context on success or NULL if it fails.
|
||||
**/
|
||||
OHMD_APIENTRYDLL ohmd_device_settings* OHMD_APIENTRY ohmd_device_settings_create(ohmd_context* ctx);
|
||||
|
||||
/**
|
||||
* Destroy a device settings instance.
|
||||
*
|
||||
* @param ctx The device settings instance to destroy.
|
||||
**/
|
||||
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_device_settings_destroy(ohmd_device_settings* settings);
|
||||
|
||||
/**
|
||||
* Close a device.
|
||||
*
|
||||
* Closes a device opened by ohmd_list_open_device. Note that ohmd_ctx_destroy automatically closes any open devices
|
||||
* associated with the context being destroyed.
|
||||
*
|
||||
* @param device The open device.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_close_device(ohmd_device* device);
|
||||
|
||||
/**
|
||||
* Get a floating point value from a device.
|
||||
*
|
||||
*
|
||||
* @param device An open device to retrieve the value from.
|
||||
* @param type What type of value to retrieve, see ohmd_float_value section for more information.
|
||||
* @param[out] out A pointer to a float, or float array where the retrieved value should be written.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_float_value type, float* out);
|
||||
|
||||
/**
|
||||
* Set a floating point value for a device.
|
||||
*
|
||||
* @param device An open device to set the value in.
|
||||
* @param type What type of value to set, see ohmd_float_value section for more information.
|
||||
* @param in A pointer to a float, or float array where the new value is stored.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, const float* in);
|
||||
|
||||
/**
|
||||
* Get an integer value from a device.
|
||||
*
|
||||
* @param device An open device to retrieve the value from.
|
||||
* @param type What type of value to retrieve, ohmd_int_value section for more information.
|
||||
* @param[out] out A pointer to an integer, or integer array where the retrieved value should be written.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out);
|
||||
|
||||
/**
|
||||
* Set an integer value for a device.
|
||||
*
|
||||
* @param device An open device to set the value in.
|
||||
* @param type What type of value to set, see ohmd_float_value section for more information.
|
||||
* @param in A pointer to a int, or int array where the new value is stored.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, const int* in);
|
||||
|
||||
/**
|
||||
* Set an void* data value for a device.
|
||||
*
|
||||
* @param device An open device to set the value in.
|
||||
* @param type What type of value to set, see ohmd_float_value section for more information.
|
||||
* @param in A pointer to the void* casted object.
|
||||
* @return 0 on success, <0 on failure.
|
||||
**/
|
||||
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, const void* in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
335
extern/openhmd/src/drv_android/android.c
vendored
Normal file
335
extern/openhmd/src/drv_android/android.c
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Copyright (C) 2015 Joey Ferwerda
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Android Driver */
|
||||
|
||||
#include "android.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/sensor.h>
|
||||
#endif // __ANDROID__
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
fusion sensor_fusion;
|
||||
|
||||
//Android specific
|
||||
#ifdef __ANDROID__
|
||||
android_app* state;
|
||||
ASensorManager* sensorManager;
|
||||
const ASensor* accelerometerSensor;
|
||||
const ASensor* gyroscopeSensor;
|
||||
ASensorEventQueue* sensorEventQueue;
|
||||
AAssetManager* assetMgr;
|
||||
short firstRun;
|
||||
#endif
|
||||
} android_priv;
|
||||
|
||||
//Forward decelerations
|
||||
static void set_android_properties(ohmd_device* device, ohmd_device_properties* props);
|
||||
static void nofusion_init(fusion* me);
|
||||
static void nofusion_update(fusion* me, float dt, const vec3f* accel);
|
||||
|
||||
|
||||
//Static variable for timeDelta;
|
||||
static float timestamp;
|
||||
|
||||
//Android callback for the sensor event queue
|
||||
static int android_sensor_callback(int fd, int events, void* data)
|
||||
{
|
||||
android_priv* priv = (android_priv*)data;
|
||||
|
||||
if (priv->accelerometerSensor != NULL)
|
||||
{
|
||||
ASensorEvent event;
|
||||
vec3f gyro;
|
||||
vec3f accel;
|
||||
vec3f mag;
|
||||
float lastevent_timestamp;
|
||||
while (ASensorEventQueue_getEvents(priv->sensorEventQueue, &event, 1) > 0)
|
||||
{
|
||||
if (event.type == ASENSOR_TYPE_ACCELEROMETER)
|
||||
{
|
||||
accel.x = event.acceleration.y;
|
||||
accel.y = -event.acceleration.x;
|
||||
accel.z = event.acceleration.z;
|
||||
}
|
||||
if (event.type == ASENSOR_TYPE_GYROSCOPE)
|
||||
{
|
||||
gyro.x = -event.data[1];
|
||||
gyro.y = event.data[0];
|
||||
gyro.z = event.data[2];
|
||||
}
|
||||
///TODO: Implement mag when available
|
||||
mag.x = 0.0f;
|
||||
mag.y = 0.0f;
|
||||
mag.z = 0.0f;
|
||||
|
||||
lastevent_timestamp = event.timestamp;
|
||||
}
|
||||
//apply data to the fusion
|
||||
float dT = 0.0f;
|
||||
if (timestamp != 0)
|
||||
dT= (lastevent_timestamp - timestamp) * (1.0f / 1000000000.0f);
|
||||
|
||||
//Check if accelerometer only fallback is required
|
||||
if (!priv->gyroscopeSensor)
|
||||
nofusion_update(&priv->sensor_fusion, dT, &accel);
|
||||
else
|
||||
ofusion_update(&priv->sensor_fusion, dT, &gyro, &accel, &mag); //default
|
||||
|
||||
timestamp = lastevent_timestamp;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
android_priv* priv = (android_priv*)device;
|
||||
|
||||
if(!priv->state)
|
||||
return;
|
||||
|
||||
//We need this since during init the android_app state is not set yet
|
||||
if (priv->firstRun == 1)
|
||||
{
|
||||
priv->sensorEventQueue = ASensorManager_createEventQueue(priv->sensorManager,
|
||||
priv->state->looper, LOOPER_ID_USER, android_sensor_callback, (void*)priv);
|
||||
|
||||
// Start sensors in case this was not done already.
|
||||
if (priv->accelerometerSensor != NULL)
|
||||
{
|
||||
ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->accelerometerSensor);
|
||||
// We'd like to get 60 events per second (in us).
|
||||
ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->accelerometerSensor, (1000L/60)*1000);
|
||||
}
|
||||
if (priv->gyroscopeSensor != NULL)
|
||||
{
|
||||
ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->gyroscopeSensor);
|
||||
// We'd like to get 60 events per second (in us).
|
||||
ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->gyroscopeSensor, (1000L/60)*1000);
|
||||
}
|
||||
priv->firstRun = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
android_priv* priv = (android_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_ROTATION_QUAT: {
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
case OHMD_DISTORTION_K:
|
||||
// TODO this should be set to the equivalent of no distortion
|
||||
memset(out, 0, sizeof(float) * 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%d)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_data(ohmd_device* device, ohmd_data_value type, void* in)
|
||||
{
|
||||
android_priv* priv = (android_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_DRIVER_DATA: {
|
||||
priv->state = (android_app*)in;
|
||||
break;
|
||||
}
|
||||
case OHMD_DRIVER_PROPERTIES: {
|
||||
set_android_properties(device, (ohmd_device_properties*)in);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to set_data (%i)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
LOGD("closing Android device");
|
||||
free(device);
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
android_priv* priv = ohmd_alloc(driver->ctx, sizeof(android_priv));
|
||||
if(!priv)
|
||||
return NULL;
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties
|
||||
//TODO: Get information from android about device
|
||||
//TODO: Use profile string to set default for a particular device (Durovis, VR One etc)
|
||||
priv->base.properties.hsize = 0.149760f;
|
||||
priv->base.properties.vsize = 0.093600f;
|
||||
priv->base.properties.hres = 1280;
|
||||
priv->base.properties.vres = 800;
|
||||
priv->base.properties.lens_sep = 0.063500f;
|
||||
priv->base.properties.lens_vpos = 0.046800f;
|
||||
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
|
||||
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
priv->base.set_data = set_data;
|
||||
|
||||
//init Android sensors
|
||||
priv->sensorManager = ASensorManager_getInstance();
|
||||
priv->accelerometerSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
|
||||
ASENSOR_TYPE_ACCELEROMETER);
|
||||
priv->gyroscopeSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
|
||||
ASENSOR_TYPE_GYROSCOPE);
|
||||
|
||||
priv->firstRun = 1; //need this since ASensorManager_createEventQueue requires a set android_app*
|
||||
|
||||
//Check if accelerometer only fallback is required
|
||||
if (!priv->gyroscopeSensor)
|
||||
nofusion_init(&priv->sensor_fusion);
|
||||
else
|
||||
ofusion_init(&priv->sensor_fusion); //Default when all sensors are available
|
||||
|
||||
return (ohmd_device*)priv;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD Generic Android Driver");
|
||||
strcpy(desc->vendor, "OpenHMD");
|
||||
strcpy(desc->product, "Android Device");
|
||||
|
||||
strcpy(desc->path, "(none)");
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down Android driver");
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_android_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
if(!drv)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
drv->ctx = ctx;
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
/* Android specific functions */
|
||||
static void nofusion_update(fusion* me, float dt, const vec3f* accel)
|
||||
{
|
||||
//avg raw accel data to smooth jitter, and normalise
|
||||
ofq_add(&me->accel_fq, accel);
|
||||
vec3f accel_mean;
|
||||
ofq_get_mean(&me->accel_fq, &accel_mean);
|
||||
vec3f acc_n = accel_mean;
|
||||
ovec3f_normalize_me(&acc_n);
|
||||
|
||||
|
||||
//reference vectors for axis-angle
|
||||
vec3f xyzv[3] = {
|
||||
{1,0,0},
|
||||
{0,1,0},
|
||||
{0,0,1}
|
||||
};
|
||||
quatf roll, pitch;
|
||||
|
||||
//pitch is rot around x, based on gravity in z and y axes
|
||||
oquatf_init_axis(&pitch, xyzv+0, atan2f(-acc_n.z, -acc_n.y));
|
||||
|
||||
//roll is rot around z, based on gravity in x and y axes
|
||||
//note we need to invert the values when the device is upside down (y < 0) for proper results
|
||||
oquatf_init_axis(&roll, xyzv+2, acc_n.y < 0 ? atan2f(-acc_n.x, -acc_n.y) : atan2f(acc_n.x, acc_n.y));
|
||||
|
||||
|
||||
|
||||
quatf or = {0,0,0,1};
|
||||
//order of applying is yaw-pitch-roll
|
||||
//yaw is not possible using only accel
|
||||
oquatf_mult_me(&or, &pitch);
|
||||
oquatf_mult_me(&or, &roll);
|
||||
|
||||
me->orient = or;
|
||||
}
|
||||
|
||||
//shorter buffers for frame smoothing
|
||||
static void nofusion_init(fusion* me)
|
||||
{
|
||||
memset(me, 0, sizeof(fusion));
|
||||
me->orient.w = 1.0f;
|
||||
|
||||
ofq_init(&me->mag_fq, 10);
|
||||
ofq_init(&me->accel_fq, 10);
|
||||
ofq_init(&me->ang_vel_fq, 10);
|
||||
|
||||
me->flags = FF_USE_GRAVITY;
|
||||
me->grav_gain = 0.05f;
|
||||
}
|
||||
|
||||
static void set_android_properties(ohmd_device* device, ohmd_device_properties* props)
|
||||
{
|
||||
android_priv* priv = (android_priv*)device;
|
||||
|
||||
priv->base.properties.hsize = props->hsize;
|
||||
priv->base.properties.vsize = props->vsize;
|
||||
priv->base.properties.hres = props->hres;
|
||||
priv->base.properties.vres = props->vres;
|
||||
priv->base.properties.lens_sep = props->lens_sep;
|
||||
priv->base.properties.lens_vpos = props->lens_vpos;
|
||||
priv->base.properties.fov = DEG_TO_RAD(props->fov);
|
||||
priv->base.properties.ratio = props->ratio;
|
||||
}
|
||||
|
||||
static void set_android_profile(ohmd_driver* driver, android_hmd_profile profile)
|
||||
{
|
||||
switch(profile){
|
||||
case DROID_DUROVIS_OPEN_DIVE: break;
|
||||
case DROID_DUROVIS_DIVE_5: break;
|
||||
case DROID_DUROVIS_DIVE_7: break;
|
||||
case DROID_CARL_ZEISS_VRONE: break;
|
||||
case DROID_GOOGLE_CARDBOARD: break;
|
||||
case DROID_NONE:
|
||||
default: break;
|
||||
}
|
||||
}
|
91
extern/openhmd/src/drv_android/android.h
vendored
Normal file
91
extern/openhmd/src/drv_android/android.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Copyright (C) 2015 Joey Ferwerda
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Android Driver */
|
||||
|
||||
#ifndef ANDROID_H
|
||||
#define ANDROID_H
|
||||
|
||||
#include "../openhmdi.h"
|
||||
|
||||
typedef enum {
|
||||
DROID_DUROVIS_OPEN_DIVE = 1,
|
||||
DROID_DUROVIS_DIVE_5 = 2,
|
||||
DROID_DUROVIS_DIVE_7 = 3,
|
||||
DROID_CARL_ZEISS_VRONE = 4,
|
||||
DROID_GOOGLE_CARDBOARD = 5,
|
||||
|
||||
DROID_NONE = 0,
|
||||
} android_hmd_profile;
|
||||
|
||||
//Android copy-paste from android_native_app_glue to be able to cast data to something useful
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
struct android_app;
|
||||
|
||||
struct android_poll_source {
|
||||
int32_t id;
|
||||
|
||||
struct android_app* app;
|
||||
|
||||
void (*process)(struct android_app* app, struct android_poll_source* source);
|
||||
};
|
||||
|
||||
typedef struct android_app {
|
||||
void* userData;
|
||||
|
||||
void (*onAppCmd)(struct android_app* app, int32_t cmd);
|
||||
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
|
||||
|
||||
ANativeActivity* activity;
|
||||
AConfiguration* config;
|
||||
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
|
||||
ALooper* looper;
|
||||
AInputQueue* inputQueue;
|
||||
ANativeWindow* window;
|
||||
ARect contentRect;
|
||||
|
||||
int activityState;
|
||||
int destroyRequested;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
struct android_poll_source cmdPollSource;
|
||||
struct android_poll_source inputPollSource;
|
||||
|
||||
int running;
|
||||
int stateSaved;
|
||||
int destroyed;
|
||||
int redrawNeeded;
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* pendingWindow;
|
||||
ARect pendingContentRect;
|
||||
} android_app;
|
||||
|
||||
enum {
|
||||
LOOPER_ID_MAIN = 1,
|
||||
LOOPER_ID_INPUT = 2,
|
||||
LOOPER_ID_USER = 3
|
||||
};
|
||||
|
||||
#endif // ANDROID_H
|
332
extern/openhmd/src/drv_deepoon/deepoon.c
vendored
Normal file
332
extern/openhmd/src/drv_deepoon/deepoon.c
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Deepoon Driver - HID/USB Driver Implementation */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <hidapi.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "deepoon.h"
|
||||
|
||||
#define TICK_LEN (1.0f / 1000000.0f) // 1000 Hz ticks
|
||||
#define KEEP_ALIVE_VALUE (10 * 1000)
|
||||
#define SETFLAG(_s, _flag, _val) (_s) = ((_s) & ~(_flag)) | ((_val) ? (_flag) : 0)
|
||||
|
||||
#define DEEPOON_ID 0x0483
|
||||
#define DEEPOON_HMD 0x5750
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
|
||||
hid_device* handle;
|
||||
pkt_sensor_range sensor_range;
|
||||
pkt_sensor_display_info display_info;
|
||||
rift_coordinate_frame coordinate_frame, hw_coordinate_frame;
|
||||
pkt_sensor_config sensor_config;
|
||||
pkt_tracker_sensor sensor;
|
||||
double last_keep_alive;
|
||||
fusion sensor_fusion;
|
||||
vec3f raw_mag, raw_accel, raw_gyro;
|
||||
} rift_priv;
|
||||
|
||||
static rift_priv* rift_priv_get(ohmd_device* device)
|
||||
{
|
||||
return (rift_priv*)device;
|
||||
}
|
||||
|
||||
static int get_feature_report(rift_priv* priv, rift_sensor_feature_cmd cmd, unsigned char* buf)
|
||||
{
|
||||
memset(buf, 0, FEATURE_BUFFER_SIZE);
|
||||
buf[0] = (unsigned char)cmd;
|
||||
return hid_get_feature_report(priv->handle, buf, FEATURE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static int send_feature_report(rift_priv* priv, const unsigned char *data, size_t length)
|
||||
{
|
||||
return hid_send_feature_report(priv->handle, data, length);
|
||||
}
|
||||
|
||||
static void set_coordinate_frame(rift_priv* priv, rift_coordinate_frame coordframe)
|
||||
{
|
||||
priv->coordinate_frame = coordframe;
|
||||
|
||||
// set the RIFT_SCF_SENSOR_COORDINATES in the sensor config to match whether coordframe is hmd or sensor
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_SENSOR_COORDINATES, coordframe == RIFT_CF_SENSOR);
|
||||
|
||||
// encode send the new config to the Rift
|
||||
unsigned char buf[FEATURE_BUFFER_SIZE];
|
||||
int size = dp_encode_sensor_config(buf, &priv->sensor_config);
|
||||
if(send_feature_report(priv, buf, size) == -1){
|
||||
ohmd_set_error(priv->base.ctx, "send_feature_report failed in set_coordinate frame");
|
||||
return;
|
||||
}
|
||||
|
||||
// read the state again, set the hw_coordinate_frame to match what
|
||||
// the hardware actually is set to just incase it doesn't stick.
|
||||
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
|
||||
if(size <= 0){
|
||||
LOGW("could not set coordinate frame");
|
||||
priv->hw_coordinate_frame = RIFT_CF_HMD;
|
||||
return;
|
||||
}
|
||||
|
||||
priv->hw_coordinate_frame = (priv->sensor_config.flags & RIFT_SCF_SENSOR_COORDINATES) ? RIFT_CF_SENSOR : RIFT_CF_HMD;
|
||||
|
||||
if(priv->hw_coordinate_frame != coordframe) {
|
||||
LOGW("coordinate frame didn't stick");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tracker_sensor_msg(rift_priv* priv, unsigned char* buffer, int size)
|
||||
{
|
||||
uint32_t last_sample_tick = priv->sensor.tick;
|
||||
|
||||
if(!dp_decode_tracker_sensor_msg(&priv->sensor, buffer, size)){
|
||||
LOGE("couldn't decode tracker sensor message");
|
||||
}
|
||||
|
||||
pkt_tracker_sensor* s = &priv->sensor;
|
||||
|
||||
dp_dump_packet_tracker_sensor(s);
|
||||
|
||||
uint32_t tick_delta = 1000;
|
||||
if(last_sample_tick > 0) //startup correction
|
||||
tick_delta = s->tick - last_sample_tick;
|
||||
|
||||
float dt = tick_delta * TICK_LEN;
|
||||
vec3f mag = {{0.0f, 0.0f, 0.0f}};
|
||||
|
||||
for(int i = 0; i < 1; i++){ //just use 1 sample since we don't have sample order for this frame
|
||||
vec3f_from_dp_vec(s->samples[i].accel, &priv->raw_accel);
|
||||
vec3f_from_dp_vec(s->samples[i].gyro, &priv->raw_gyro);
|
||||
|
||||
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &mag);
|
||||
|
||||
// reset dt to tick_len for the last samples if there were more than one sample
|
||||
dt = TICK_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
unsigned char buffer[FEATURE_BUFFER_SIZE];
|
||||
|
||||
// Handle keep alive messages
|
||||
double t = ohmd_get_tick();
|
||||
if(t - priv->last_keep_alive >= (double)priv->sensor_config.keep_alive_interval / 1000.0 - .2){
|
||||
// send keep alive message
|
||||
pkt_keep_alive keep_alive = { 0, priv->sensor_config.keep_alive_interval };
|
||||
int ka_size = dp_encode_keep_alive(buffer, &keep_alive);
|
||||
send_feature_report(priv, buffer, ka_size);
|
||||
|
||||
// Update the time of the last keep alive we have sent.
|
||||
priv->last_keep_alive = t;
|
||||
}
|
||||
|
||||
// Read all the messages from the device.
|
||||
while(true){
|
||||
int size = hid_read(priv->handle, buffer, FEATURE_BUFFER_SIZE);
|
||||
if(size < 0){
|
||||
LOGE("error reading from device");
|
||||
return;
|
||||
} else if(size == 0) {
|
||||
return; // No more messages, return.
|
||||
}
|
||||
|
||||
// currently the only message type the hardware supports (I think)
|
||||
if(buffer[0] == RIFT_IRQ_SENSORS || buffer[0] == 11){
|
||||
handle_tracker_sensor_msg(priv, buffer, size);
|
||||
}else{
|
||||
LOGE("unknown message type: %u", buffer[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
|
||||
switch(type){
|
||||
case OHMD_DISTORTION_K: {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
out[i] = priv->display_info.distortion_k[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_ROTATION_QUAT: {
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
LOGD("closing device");
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
hid_close(priv->handle);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
static char* _hid_to_unix_path(char* path)
|
||||
{
|
||||
char bus [4];
|
||||
char dev [4];
|
||||
char *result = malloc( sizeof(char) * ( 20 + 1 ) );
|
||||
|
||||
sprintf (bus, "%.*s\n", 4, path);
|
||||
sprintf (dev, "%.*s\n", 4, path + 5);
|
||||
|
||||
sprintf (result, "/dev/bus/usb/%03d/%03d",
|
||||
(int)strtol(bus, NULL, 16),
|
||||
(int)strtol(dev, NULL, 16));
|
||||
return result;
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
rift_priv* priv = ohmd_alloc(driver->ctx, sizeof(rift_priv));
|
||||
if(!priv)
|
||||
goto cleanup;
|
||||
|
||||
priv->base.ctx = driver->ctx;
|
||||
|
||||
// Open the HID device
|
||||
priv->handle = hid_open_path(desc->path);
|
||||
|
||||
if(!priv->handle) {
|
||||
char* path = _hid_to_unix_path(desc->path);
|
||||
ohmd_set_error(driver->ctx, "Could not open %s. "
|
||||
"Check your rights.", path);
|
||||
free(path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(hid_set_nonblocking(priv->handle, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
unsigned char buf[FEATURE_BUFFER_SIZE];
|
||||
|
||||
int size;
|
||||
|
||||
// if the sensor has display info data, use HMD coordinate frame
|
||||
priv->coordinate_frame = priv->display_info.distortion_type != RIFT_DT_NONE ? RIFT_CF_HMD : RIFT_CF_SENSOR;
|
||||
|
||||
// enable calibration
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_USE_CALIBRATION, 1);
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_AUTO_CALIBRATION, 1);
|
||||
|
||||
// apply sensor config
|
||||
set_coordinate_frame(priv, priv->coordinate_frame);
|
||||
|
||||
// set keep alive interval to n seconds
|
||||
pkt_keep_alive keep_alive = { 0, KEEP_ALIVE_VALUE };
|
||||
size = dp_encode_keep_alive(buf, &keep_alive);
|
||||
send_feature_report(priv, buf, size);
|
||||
|
||||
// Update the time of the last keep alive we have sent.
|
||||
priv->last_keep_alive = ohmd_get_tick();
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties
|
||||
//NOTE: These values are estimations, no one has taken one appart to check
|
||||
priv->base.properties.hsize = 0.1698f;
|
||||
priv->base.properties.vsize = 0.0936f;
|
||||
priv->base.properties.hres = 1920;
|
||||
priv->base.properties.vres = 1080;
|
||||
priv->base.properties.lens_sep = 0.0849f;
|
||||
priv->base.properties.lens_vpos = 0.0468f;;
|
||||
priv->base.properties.fov = DEG_TO_RAD(110.0); // TODO calculate.
|
||||
priv->base.properties.ratio = ((float)1920 / (float)1080) / 2.0f;
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
|
||||
// initialize sensor fusion
|
||||
ofusion_init(&priv->sensor_fusion);
|
||||
|
||||
return &priv->base;
|
||||
|
||||
cleanup:
|
||||
if(priv)
|
||||
free(priv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
struct hid_device_info* devs = hid_enumerate(DEEPOON_ID, DEEPOON_HMD);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
while (cur_dev) {
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "Deepoon Driver");
|
||||
strcpy(desc->vendor, "Deepoon");
|
||||
strcpy(desc->product, "Deepoon E2");
|
||||
|
||||
desc->revision = 0;
|
||||
|
||||
strcpy(desc->path, cur_dev->path);
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down driver");
|
||||
hid_exit();
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_deepoon_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
if(drv == NULL)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->ctx = ctx;
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
|
||||
return drv;
|
||||
}
|
111
extern/openhmd/src/drv_deepoon/deepoon.h
vendored
Normal file
111
extern/openhmd/src/drv_deepoon/deepoon.h
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Deepoon Driver Internal Interface */
|
||||
|
||||
#ifndef DEEPOON_H
|
||||
#define DEEPOON_H
|
||||
|
||||
#include "../openhmdi.h"
|
||||
|
||||
#define FEATURE_BUFFER_SIZE 256
|
||||
|
||||
typedef enum {
|
||||
RIFT_CMD_SENSOR_CONFIG = 2,
|
||||
RIFT_CMD_RANGE = 4,
|
||||
RIFT_CMD_KEEP_ALIVE = 8,
|
||||
RIFT_CMD_DISPLAY_INFO = 9
|
||||
} rift_sensor_feature_cmd;
|
||||
|
||||
typedef enum {
|
||||
RIFT_CF_SENSOR,
|
||||
RIFT_CF_HMD
|
||||
} rift_coordinate_frame;
|
||||
|
||||
typedef enum {
|
||||
RIFT_IRQ_SENSORS = 1
|
||||
} rift_irq_cmd;
|
||||
|
||||
typedef enum {
|
||||
RIFT_DT_NONE,
|
||||
RIFT_DT_SCREEN_ONLY,
|
||||
RIFT_DT_DISTORTION
|
||||
} rift_distortion_type;
|
||||
|
||||
// Sensor config flags
|
||||
#define RIFT_SCF_RAW_MODE 0x01
|
||||
#define RIFT_SCF_CALIBRATION_TEST 0x02
|
||||
#define RIFT_SCF_USE_CALIBRATION 0x04
|
||||
#define RIFT_SCF_AUTO_CALIBRATION 0x08
|
||||
#define RIFT_SCF_MOTION_KEEP_ALIVE 0x10
|
||||
#define RIFT_SCF_COMMAND_KEEP_ALIVE 0x20
|
||||
#define RIFT_SCF_SENSOR_COORDINATES 0x40
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint16_t accel_scale;
|
||||
uint16_t gyro_scale;
|
||||
uint16_t mag_scale;
|
||||
} pkt_sensor_range;
|
||||
|
||||
typedef struct {
|
||||
int32_t accel[3];
|
||||
int32_t gyro[3];
|
||||
} pkt_tracker_sample;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
uint8_t sample_delta;
|
||||
uint16_t sample_number;
|
||||
uint32_t tick;
|
||||
pkt_tracker_sample samples[2];
|
||||
int16_t mag[3];
|
||||
} pkt_tracker_sensor;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint8_t flags;
|
||||
uint16_t packet_interval;
|
||||
uint16_t keep_alive_interval; // in ms
|
||||
} pkt_sensor_config;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
rift_distortion_type distortion_type;
|
||||
uint8_t distortion_type_opts;
|
||||
uint16_t h_resolution, v_resolution;
|
||||
float h_screen_size, v_screen_size;
|
||||
float v_center;
|
||||
float lens_separation;
|
||||
float eye_to_screen_distance[2];
|
||||
float distortion_k[6];
|
||||
} pkt_sensor_display_info;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint16_t keep_alive_interval;
|
||||
} pkt_keep_alive;
|
||||
|
||||
|
||||
bool dp_decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size);
|
||||
bool dp_decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size);
|
||||
bool dp_decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size);
|
||||
bool dp_decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
|
||||
|
||||
void vec3f_from_dp_vec(const int32_t* smp, vec3f* out_vec);
|
||||
|
||||
int dp_encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config);
|
||||
int dp_encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive);
|
||||
|
||||
void dp_dump_packet_sensor_range(const pkt_sensor_range* range);
|
||||
void dp_dump_packet_sensor_config(const pkt_sensor_config* config);
|
||||
void dp_dump_packet_sensor_display_info(const pkt_sensor_display_info* info);
|
||||
void dp_dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor);
|
||||
|
||||
#endif
|
182
extern/openhmd/src/drv_deepoon/packet.c
vendored
Normal file
182
extern/openhmd/src/drv_deepoon/packet.c
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Deepoon Driver - Packet Decoding and Utilities */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "deepoon.h"
|
||||
|
||||
#define SKIP_CMD (buffer++)
|
||||
#define READ8 *(buffer++);
|
||||
#define READ16 *buffer | (*(buffer + 1) << 8); buffer += 2;
|
||||
#define READ32 *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24); buffer += 4;
|
||||
#define READFLOAT ((float)(*buffer)); buffer += 4;
|
||||
#define READFIXED (float)(*buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24)) / 1000000.0f; buffer += 4;
|
||||
|
||||
#define WRITE8(_val) *(buffer++) = (_val);
|
||||
#define WRITE16(_val) WRITE8((_val) & 0xff); WRITE8(((_val) >> 8) & 0xff);
|
||||
#define WRITE32(_val) WRITE16((_val) & 0xffff) *buffer; WRITE16(((_val) >> 16) & 0xffff);
|
||||
|
||||
bool dp_decodesensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 8 || size == 9)){
|
||||
LOGE("invalid packet size (expected 8 or 9 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
range->command_id = READ16;
|
||||
range->accel_scale = READ8;
|
||||
range->gyro_scale = READ16;
|
||||
range->mag_scale = READ16;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dp_decodesensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 56 || size == 57)){
|
||||
LOGE("invalid packet size (expected 56 or 57 but got %d)", size);
|
||||
//return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
info->command_id = READ16;
|
||||
info->distortion_type = READ8;
|
||||
info->h_resolution = READ16;
|
||||
info->v_resolution = READ16;
|
||||
info->h_screen_size = READFIXED;
|
||||
info->v_screen_size = READFIXED;
|
||||
info->v_center = READFIXED;
|
||||
info->lens_separation = READFIXED;
|
||||
info->eye_to_screen_distance[0] = READFIXED;
|
||||
info->eye_to_screen_distance[1] = READFIXED;
|
||||
|
||||
info->distortion_type_opts = 0;
|
||||
|
||||
for(int i = 0; i < 6; i++){
|
||||
info->distortion_k[i] = READFLOAT;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dp_decodesensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 7 || size == 8)){
|
||||
LOGE("invalid packet size (expected 7 or 8 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
config->command_id = READ16;
|
||||
config->flags = READ8;
|
||||
config->packet_interval = READ8;
|
||||
config->keep_alive_interval = READ16;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dp_decodesample(const unsigned char* buffer, int32_t* smp)
|
||||
{
|
||||
/*
|
||||
* Decode 3 tightly packed 21 bit values from 4 bytes.
|
||||
* We unpack them in the higher 21 bit values first and then shift
|
||||
* them down to the lower in order to get the sign bits correct.
|
||||
*/
|
||||
|
||||
int x = (buffer[0] << 24) | (buffer[1] << 16) | ((buffer[2] & 0xF8) << 8);
|
||||
int y = ((buffer[2] & 0x07) << 29) | (buffer[3] << 21) | (buffer[4] << 13) | ((buffer[5] & 0xC0) << 5);
|
||||
int z = ((buffer[5] & 0x3F) << 26) | (buffer[6] << 18) | (buffer[7] << 10);
|
||||
|
||||
smp[0] = x >> 11;
|
||||
smp[1] = y >> 11;
|
||||
smp[2] = z >> 11;
|
||||
}
|
||||
|
||||
bool dp_decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 62 || size == 64)){
|
||||
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
msg->report_id = READ8;
|
||||
buffer += 2;
|
||||
msg->sample_delta = READ8;
|
||||
msg->sample_number = READ16;
|
||||
buffer += 2;
|
||||
msg->tick = READ32;
|
||||
|
||||
for(int i = 0; i < 2; i++){
|
||||
dp_decodesample(buffer, msg->samples[i].accel);
|
||||
buffer += 8;
|
||||
|
||||
dp_decodesample(buffer, msg->samples[i].gyro);
|
||||
buffer += 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO do we need to consider HMD vs sensor "centric" values
|
||||
void vec3f_from_dp_vec(const int32_t* smp, vec3f* out_vec)
|
||||
{
|
||||
out_vec->x = (float)smp[0] * 0.0001f;
|
||||
out_vec->y = ((float)smp[2] * 0.0001f) * -1;
|
||||
out_vec->z = (float)smp[1] * 0.0001f;
|
||||
}
|
||||
|
||||
int dp_encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config)
|
||||
{
|
||||
WRITE8(RIFT_CMD_SENSOR_CONFIG);
|
||||
WRITE16(config->command_id);
|
||||
WRITE8(config->flags);
|
||||
WRITE8(config->packet_interval);
|
||||
WRITE16(config->keep_alive_interval);
|
||||
return 7; // sensor config packet size
|
||||
}
|
||||
|
||||
int dp_encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive)
|
||||
{
|
||||
WRITE8(RIFT_CMD_KEEP_ALIVE);
|
||||
WRITE16(keep_alive->command_id);
|
||||
WRITE16(keep_alive->keep_alive_interval);
|
||||
return 5; // keep alive packet size
|
||||
}
|
||||
|
||||
void dp_dump_packet_sensor_config(const pkt_sensor_config* config)
|
||||
{
|
||||
(void)config;
|
||||
|
||||
LOGD("sensor config");
|
||||
LOGD(" command id: %u", config->command_id);
|
||||
LOGD(" flags: %02x", config->flags);
|
||||
LOGD(" raw mode: %d", !!(config->flags & RIFT_SCF_RAW_MODE));
|
||||
LOGD(" calibration test: %d", !!(config->flags & RIFT_SCF_CALIBRATION_TEST));
|
||||
LOGD(" use calibration: %d", !!(config->flags & RIFT_SCF_USE_CALIBRATION));
|
||||
LOGD(" auto calibration: %d", !!(config->flags & RIFT_SCF_AUTO_CALIBRATION));
|
||||
LOGD(" motion keep alive: %d", !!(config->flags & RIFT_SCF_MOTION_KEEP_ALIVE));
|
||||
LOGD(" motion command keep alive: %d", !!(config->flags & RIFT_SCF_COMMAND_KEEP_ALIVE));
|
||||
LOGD(" sensor coordinates: %d", !!(config->flags & RIFT_SCF_SENSOR_COORDINATES));
|
||||
LOGD(" packet interval: %u", config->packet_interval);
|
||||
LOGD(" keep alive interval: %u", config->keep_alive_interval);
|
||||
}
|
||||
|
||||
void dp_dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor)
|
||||
{
|
||||
(void)sensor;
|
||||
LOGD("TEST: deepoon sensor data");
|
||||
LOGD(" report id: %u", sensor->report_id);
|
||||
LOGD(" sample delta: %u", sensor->sample_delta);
|
||||
LOGD(" sample number: %d", sensor->sample_number);
|
||||
LOGD(" tick: %u", sensor->tick);
|
||||
for(int i = 0; i < 2; i++){
|
||||
LOGD(" accel: %d %d %d", sensor->samples[i].accel[0], sensor->samples[i].accel[1], sensor->samples[i].accel[2]);
|
||||
LOGD(" gyro: %d %d %d", sensor->samples[i].gyro[0], sensor->samples[i].gyro[1], sensor->samples[i].gyro[2]);
|
||||
}
|
||||
}
|
118
extern/openhmd/src/drv_dummy/dummy.c
vendored
Normal file
118
extern/openhmd/src/drv_dummy/dummy.c
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Dummy Driver */
|
||||
|
||||
#include <string.h>
|
||||
#include "../openhmdi.h"
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
} dummy_priv;
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
dummy_priv* priv = (dummy_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_ROTATION_QUAT:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
out[3] = 1.0f;
|
||||
break;
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
case OHMD_DISTORTION_K:
|
||||
// TODO this should be set to the equivalent of no distortion
|
||||
memset(out, 0, sizeof(float) * 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
LOGD("closing dummy device");
|
||||
free(device);
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
dummy_priv* priv = ohmd_alloc(driver->ctx, sizeof(dummy_priv));
|
||||
if(!priv)
|
||||
return NULL;
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties (imitates the rift values)
|
||||
priv->base.properties.hsize = 0.149760f;
|
||||
priv->base.properties.vsize = 0.093600f;
|
||||
priv->base.properties.hres = 1280;
|
||||
priv->base.properties.vres = 800;
|
||||
priv->base.properties.lens_sep = 0.063500f;
|
||||
priv->base.properties.lens_vpos = 0.046800f;
|
||||
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
|
||||
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
|
||||
priv->base.properties.digital_button_count = 4;
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
|
||||
return (ohmd_device*)priv;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD Dummy Driver");
|
||||
strcpy(desc->vendor, "OpenHMD");
|
||||
strcpy(desc->product, "Dummy Device");
|
||||
|
||||
strcpy(desc->path, "(none)");
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down dummy driver");
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_dummy_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
if(!drv)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
|
||||
return drv;
|
||||
}
|
152
extern/openhmd/src/drv_external/external.c
vendored
Normal file
152
extern/openhmd/src/drv_external/external.c
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Copyright (C) 2015 Joey Ferwerda
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* External Driver */
|
||||
|
||||
#include "../openhmdi.h"
|
||||
#include "string.h"
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
fusion sensor_fusion;
|
||||
} external_priv;
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
external_priv* priv = (external_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_ROTATION_QUAT: {
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%d)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setf(ohmd_device* device, ohmd_float_value type, const float* in)
|
||||
{
|
||||
external_priv* priv = (external_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_EXTERNAL_SENSOR_FUSION: {
|
||||
ofusion_update(&priv->sensor_fusion, *in, (vec3f*)(in + 1), (vec3f*)(in + 4), (vec3f*)(in + 7));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to setf (%d)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
LOGD("closing external device");
|
||||
free(device);
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
external_priv* priv = ohmd_alloc(driver->ctx, sizeof(external_priv));
|
||||
if(!priv)
|
||||
return NULL;
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties
|
||||
//TODO: Get information from external device using set_external_properties?
|
||||
//Using 'dummy' settings for now
|
||||
priv->base.properties.hsize = 0.149760f;
|
||||
priv->base.properties.vsize = 0.093600f;
|
||||
priv->base.properties.hres = 1280;
|
||||
priv->base.properties.vres = 800;
|
||||
priv->base.properties.lens_sep = 0.063500f;
|
||||
priv->base.properties.lens_vpos = 0.046800f;
|
||||
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
|
||||
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
priv->base.setf = setf;
|
||||
|
||||
ofusion_init(&priv->sensor_fusion);
|
||||
|
||||
return (ohmd_device*)priv;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD Generic External Driver");
|
||||
strcpy(desc->vendor, "OpenHMD");
|
||||
strcpy(desc->product, "External Device");
|
||||
|
||||
strcpy(desc->path, "(none)");
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down external driver");
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_external_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
if(!drv)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
drv->ctx = ctx;
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
/* external specific functions */
|
||||
/*static void set_external_properties(ohmd_device* device, ohmd_device_properties* props)
|
||||
{
|
||||
external_priv* priv = (external_priv*)device;
|
||||
|
||||
priv->base.properties.hsize = props->hsize;
|
||||
priv->base.properties.vsize = props->vsize;
|
||||
priv->base.properties.hres = props->hres;
|
||||
priv->base.properties.vres = props->vres;
|
||||
priv->base.properties.lens_sep = props->lens_sep;
|
||||
priv->base.properties.lens_vpos = props->lens_vpos;
|
||||
priv->base.properties.fov = DEG_TO_RAD(props->fov);
|
||||
priv->base.properties.ratio = props->ratio;
|
||||
}*/
|
1
extern/openhmd/src/drv_htc_vive/config.h
vendored
Normal file
1
extern/openhmd/src/drv_htc_vive/config.h
vendored
Normal file
@@ -0,0 +1 @@
|
||||
//Reserved
|
27
extern/openhmd/src/drv_htc_vive/magic.h
vendored
Normal file
27
extern/openhmd/src/drv_htc_vive/magic.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
static const unsigned char vive_magic_power_on[64] = {
|
||||
0x04, 0x78, 0x29, 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
|
||||
0xa8, 0x0d, 0x76, 0x00, 0x40, 0xfc, 0x01, 0x05, 0xfa, 0xec, 0xd1, 0x6d, 0x00,
|
||||
0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0d, 0x76, 0x00, 0x68, 0xfc,
|
||||
0x01, 0x05, 0x2c, 0xb0, 0x2e, 0x65, 0x7a, 0x0d, 0x76, 0x00, 0x68, 0x54, 0x72,
|
||||
0x00, 0x18, 0x54, 0x72, 0x00, 0x00, 0x6a, 0x72, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char vive_magic_power_off1[64] = {
|
||||
0x04, 0x78, 0x29, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x30, 0x05, 0x77, 0x00, 0x30, 0x05, 0x77, 0x00, 0x6c, 0x4d, 0x37, 0x65, 0x40,
|
||||
0xf9, 0x33, 0x00, 0x04, 0xf8, 0xa3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x70, 0xb0,
|
||||
0x72, 0x00, 0xf4, 0xf7, 0xa3, 0x04, 0x7c, 0xf8, 0x33, 0x00, 0x0c, 0xf8, 0xa3,
|
||||
0x04, 0x0a, 0x6e, 0x29, 0x65, 0x24, 0xf9, 0x33, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char vive_magic_power_off2[64] = {
|
||||
0x04, 0x78, 0x29, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x30, 0x05, 0x77, 0x00, 0xe4, 0xf7, 0x33, 0x00, 0xe4, 0xf7, 0x33, 0x00, 0x60,
|
||||
0x6e, 0x72, 0x00, 0xb4, 0xf7, 0x33, 0x00, 0x04, 0x00, 0x00, 0x00, 0x70, 0xb0,
|
||||
0x72, 0x00, 0x90, 0xf7, 0x33, 0x00, 0x7c, 0xf8, 0x33, 0x00, 0xd0, 0xf7, 0x33,
|
||||
0x00, 0x3c, 0x68, 0x29, 0x65, 0x24, 0xf9, 0x33, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char vive_magic_enable_lighthouse[5] = {
|
||||
0x04
|
||||
};
|
63
extern/openhmd/src/drv_htc_vive/packet.c
vendored
Normal file
63
extern/openhmd/src/drv_htc_vive/packet.c
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "vive.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
inline static uint8_t read8(const unsigned char** buffer)
|
||||
{
|
||||
uint8_t ret = **buffer;
|
||||
*buffer += 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static int16_t read16(const unsigned char** buffer)
|
||||
{
|
||||
int16_t ret = **buffer | (*(*buffer + 1) << 8);
|
||||
*buffer += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static uint32_t read32(const unsigned char** buffer)
|
||||
{
|
||||
uint32_t ret = **buffer | (*(*buffer + 1) << 8) | (*(*buffer + 2) << 16) | (*(*buffer + 3) << 24);
|
||||
*buffer += 4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vive_decode_sensor_packet(vive_sensor_packet* pkt, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(size != 52){
|
||||
LOGE("invalid vive sensor packet size (expected 52 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
pkt->report_id = read8(&buffer);
|
||||
|
||||
for(int j = 0; j < 3; j++){
|
||||
// acceleration
|
||||
for(int i = 0; i < 3; i++){
|
||||
pkt->samples[j].acc[i] = read16(&buffer);
|
||||
}
|
||||
|
||||
// rotation
|
||||
for(int i = 0; i < 3; i++){
|
||||
pkt->samples[j].rot[i] = read16(&buffer);
|
||||
}
|
||||
|
||||
pkt->samples[j].time_ticks = read32(&buffer);
|
||||
pkt->samples[j].seq = read8(&buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//TODO: Implement config packet decoding.
|
||||
bool vive_decode_config_packet(vive_config_packet* pkt, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(size != 64){
|
||||
LOGE("invalid vive sensor packet size (expected 64 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
441
extern/openhmd/src/drv_htc_vive/vive.c
vendored
Normal file
441
extern/openhmd/src/drv_htc_vive/vive.c
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* HTC Vive Driver */
|
||||
|
||||
#define FEATURE_BUFFER_SIZE 256
|
||||
|
||||
#define HTC_ID 0x0bb4
|
||||
#define VIVE_HMD 0x2c87
|
||||
|
||||
#define VALVE_ID 0x28de
|
||||
#define VIVE_WATCHMAN_DONGLE 0x2101
|
||||
#define VIVE_LIGHTHOUSE_FPGA_RX 0x2000
|
||||
|
||||
#define VIVE_TIME_DIV 48000000.0f
|
||||
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <hidapi.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "vive.h"
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
|
||||
hid_device* hmd_handle;
|
||||
hid_device* imu_handle;
|
||||
fusion sensor_fusion;
|
||||
vec3f raw_accel, raw_gyro;
|
||||
uint32_t last_ticks;
|
||||
uint8_t last_seq;
|
||||
|
||||
vec3f gyro_error;
|
||||
filter_queue gyro_q;
|
||||
} vive_priv;
|
||||
|
||||
void vec3f_from_vive_vec_accel(const int16_t* smp, vec3f* out_vec)
|
||||
{
|
||||
float gravity = 9.81f;
|
||||
float scaler = 4.0f * gravity / 32768.0f;
|
||||
|
||||
out_vec->x = (float)smp[0] * scaler;
|
||||
out_vec->y = (float)smp[1] * scaler * -1;
|
||||
out_vec->z = (float)smp[2] * scaler * -1;
|
||||
}
|
||||
|
||||
void vec3f_from_vive_vec_gyro(const int16_t* smp, vec3f* out_vec)
|
||||
{
|
||||
float scaler = 8.7f / 32768.0f;
|
||||
out_vec->x = (float)smp[0] * scaler;
|
||||
out_vec->y = (float)smp[1] * scaler * -1;
|
||||
out_vec->z = (float)smp[2] * scaler * -1;
|
||||
}
|
||||
|
||||
static bool process_error(vive_priv* priv)
|
||||
{
|
||||
if(priv->gyro_q.at >= priv->gyro_q.size - 1)
|
||||
return true;
|
||||
|
||||
ofq_add(&priv->gyro_q, &priv->raw_gyro);
|
||||
|
||||
if(priv->gyro_q.at >= priv->gyro_q.size - 1){
|
||||
ofq_get_mean(&priv->gyro_q, &priv->gyro_error);
|
||||
printf("gyro error: %f, %f, %f\n", priv->gyro_error.x, priv->gyro_error.y, priv->gyro_error.z);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vive_sensor_sample* get_next_sample(vive_sensor_packet* pkt, int last_seq)
|
||||
{
|
||||
int diff[3];
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
diff[i] = (int)pkt->samples[i].seq - last_seq;
|
||||
|
||||
if(diff[i] < -128){
|
||||
diff[i] += 256;
|
||||
}
|
||||
}
|
||||
|
||||
int closest_diff = INT_MAX;
|
||||
int closest_idx = -1;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if(diff[i] < closest_diff && diff[i] > 0 && diff[i] < 128){
|
||||
closest_diff = diff[i];
|
||||
closest_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(closest_idx != -1)
|
||||
return pkt->samples + closest_idx;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
vive_priv* priv = (vive_priv*)device;
|
||||
|
||||
int size = 0;
|
||||
unsigned char buffer[FEATURE_BUFFER_SIZE];
|
||||
|
||||
while((size = hid_read(priv->imu_handle, buffer, FEATURE_BUFFER_SIZE)) > 0){
|
||||
if(buffer[0] == VIVE_IRQ_SENSORS){
|
||||
vive_sensor_packet pkt;
|
||||
vive_decode_sensor_packet(&pkt, buffer, size);
|
||||
|
||||
vive_sensor_sample* smp = NULL;
|
||||
|
||||
while((smp = get_next_sample(&pkt, priv->last_seq)) != NULL)
|
||||
{
|
||||
if(priv->last_ticks == 0)
|
||||
priv->last_ticks = smp->time_ticks;
|
||||
|
||||
uint32_t t1, t2;
|
||||
t1 = smp->time_ticks;
|
||||
t2 = priv->last_ticks;
|
||||
|
||||
float dt = (t1 - t2) / VIVE_TIME_DIV;
|
||||
|
||||
priv->last_ticks = smp->time_ticks;
|
||||
|
||||
vec3f_from_vive_vec_accel(smp->acc, &priv->raw_accel);
|
||||
vec3f_from_vive_vec_gyro(smp->rot, &priv->raw_gyro);
|
||||
|
||||
if(process_error(priv)){
|
||||
vec3f mag = {{0.0f, 0.0f, 0.0f}};
|
||||
vec3f gyro;
|
||||
ovec3f_subtract(&priv->raw_gyro, &priv->gyro_error, &gyro);
|
||||
|
||||
ofusion_update(&priv->sensor_fusion, dt, &gyro, &priv->raw_accel, &mag);
|
||||
}
|
||||
|
||||
priv->last_seq = smp->seq;
|
||||
}
|
||||
}else{
|
||||
LOGE("unknown message type: %u", buffer[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if(size < 0){
|
||||
LOGE("error reading from device");
|
||||
}
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
vive_priv* priv = (vive_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_ROTATION_QUAT:
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
case OHMD_DISTORTION_K:
|
||||
// TODO this should be set to the equivalent of no distortion
|
||||
memset(out, 0, sizeof(float) * 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
int hret = 0;
|
||||
vive_priv* priv = (vive_priv*)device;
|
||||
|
||||
LOGD("closing HTC Vive device");
|
||||
|
||||
// turn the display off
|
||||
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off1, sizeof(vive_magic_power_off1));
|
||||
//printf("power off magic 1: %d\n", hret);
|
||||
|
||||
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off2, sizeof(vive_magic_power_off2));
|
||||
//printf("power off magic 2: %d\n", hret);
|
||||
|
||||
hid_close(priv->hmd_handle);
|
||||
hid_close(priv->imu_handle);
|
||||
|
||||
free(device);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dump_indexed_string(hid_device* device, int index)
|
||||
{
|
||||
wchar_t wbuffer[512] = {0};
|
||||
char buffer[1024] = {0};
|
||||
|
||||
int hret = hid_get_indexed_string(device, index, wbuffer, 511);
|
||||
|
||||
if(hret == 0){
|
||||
wcstombs(buffer, wbuffer, sizeof(buffer));
|
||||
printf("indexed string 0x%02x: '%s'\n", index, buffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dump_info_string(int (*fun)(hid_device*, wchar_t*, size_t), const char* what, hid_device* device)
|
||||
{
|
||||
wchar_t wbuffer[512] = {0};
|
||||
char buffer[1024] = {0};
|
||||
|
||||
int hret = fun(device, wbuffer, 511);
|
||||
|
||||
if(hret == 0){
|
||||
wcstombs(buffer, wbuffer, sizeof(buffer));
|
||||
printf("%s: '%s'\n", what, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dumpbin(const char* label, const unsigned char* data, int length)
|
||||
{
|
||||
printf("%s:\n", label);
|
||||
for(int i = 0; i < length; i++){
|
||||
printf("%02x ", data[i]);
|
||||
if((i % 16) == 15)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
|
||||
{
|
||||
struct hid_device_info* devs = hid_enumerate(manufacturer, product);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
int idx = 0;
|
||||
int iface_cur = 0;
|
||||
hid_device* ret = NULL;
|
||||
|
||||
while (cur_dev) {
|
||||
printf("%04x:%04x %s\n", manufacturer, product, cur_dev->path);
|
||||
|
||||
if(idx == device_index && iface == iface_cur){
|
||||
ret = hid_open_path(cur_dev->path);
|
||||
printf("opening\n");
|
||||
}
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
|
||||
iface_cur++;
|
||||
|
||||
if(iface_cur >= iface_tot){
|
||||
idx++;
|
||||
iface_cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
vive_priv* priv = ohmd_alloc(driver->ctx, sizeof(vive_priv));
|
||||
|
||||
if(!priv)
|
||||
return NULL;
|
||||
|
||||
int hret = 0;
|
||||
|
||||
priv->base.ctx = driver->ctx;
|
||||
|
||||
int idx = atoi(desc->path);
|
||||
|
||||
// Open the HMD device
|
||||
priv->hmd_handle = open_device_idx(HTC_ID, VIVE_HMD, 0, 1, idx);
|
||||
|
||||
if(!priv->hmd_handle)
|
||||
goto cleanup;
|
||||
|
||||
if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Open the lighthouse device
|
||||
priv->imu_handle = open_device_idx(VALVE_ID, VIVE_LIGHTHOUSE_FPGA_RX, 0, 2, idx);
|
||||
|
||||
if(!priv->imu_handle)
|
||||
goto cleanup;
|
||||
|
||||
if(hid_set_nonblocking(priv->imu_handle, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dump_info_string(hid_get_manufacturer_string, "manufacturer", priv->hmd_handle);
|
||||
dump_info_string(hid_get_product_string , "product", priv->hmd_handle);
|
||||
dump_info_string(hid_get_serial_number_string, "serial number", priv->hmd_handle);
|
||||
|
||||
// turn the display on
|
||||
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_on, sizeof(vive_magic_power_on));
|
||||
printf("power on magic: %d\n", hret);
|
||||
|
||||
// enable lighthouse
|
||||
//hret = hid_send_feature_report(priv->hmd_handle, vive_magic_enable_lighthouse, sizeof(vive_magic_enable_lighthouse));
|
||||
//printf("enable lighthouse magic: %d\n", hret);
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties TODO: Get from device
|
||||
priv->base.properties.hsize = 0.122822f;
|
||||
priv->base.properties.vsize = 0.068234f;
|
||||
priv->base.properties.hres = 2160;
|
||||
priv->base.properties.vres = 1200;
|
||||
/*
|
||||
// calculated from here: https://www.gamedev.net/topic/683698-projection-matrix-model-of-the-htc-vive/
|
||||
priv->base.properties.lens_sep = 0.057863;
|
||||
priv->base.properties.lens_vpos = 0.033896;
|
||||
*/
|
||||
// estimated 'by eye' on jsarret's vive
|
||||
priv->base.properties.lens_sep = 0.056;
|
||||
priv->base.properties.lens_vpos = 0.032;
|
||||
float eye_to_screen_distance = 0.023226876441867737;
|
||||
//priv->base.properties.fov = DEG_TO_RAD(111.435f); //TODO: Confirm exact mesurements
|
||||
priv->base.properties.ratio = (2160.0f / 1200.0f) / 2.0f;
|
||||
|
||||
/*
|
||||
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.394119, -0.508383, 0.323322, 0.790942);
|
||||
*/
|
||||
ohmd_set_universal_distortion_k(&(priv->base.properties), 1.318397, -1.490242, 0.663824, 0.508021);
|
||||
ohmd_set_universal_aberration_k(&(priv->base.properties), 1.00010147892f, 1.000f, 1.00019614479f);
|
||||
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
//ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
float l,r,t,b,n,f;
|
||||
// left eye screen bounds
|
||||
l = -1.0f * (priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2);
|
||||
r = priv->base.properties.lens_sep/2;
|
||||
t = priv->base.properties.vsize - priv->base.properties.lens_vpos;
|
||||
b = -1.0f * priv->base.properties.lens_vpos;
|
||||
n = eye_to_screen_distance;
|
||||
f = n*10e6;
|
||||
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
|
||||
/* eye separation is handled by IPD in the Modelview matrix */
|
||||
omat4x4f_init_frustum(&priv->base.properties.proj_left, l, r, b, t, n, f);
|
||||
//right eye screen bounds
|
||||
l = -1.0f * priv->base.properties.lens_sep/2;
|
||||
r = priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2;
|
||||
n = eye_to_screen_distance;
|
||||
f = n*10e6;
|
||||
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
|
||||
/* eye separation is handled by IPD in the Modelview matrix */
|
||||
omat4x4f_init_frustum(&priv->base.properties.proj_right, l, r, b, t, n, f);
|
||||
|
||||
priv->base.properties.fov = 2 * atan2f(
|
||||
priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2,
|
||||
eye_to_screen_distance);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
|
||||
ofusion_init(&priv->sensor_fusion);
|
||||
|
||||
ofq_init(&priv->gyro_q, 128);
|
||||
|
||||
return (ohmd_device*)priv;
|
||||
|
||||
cleanup:
|
||||
if(priv)
|
||||
free(priv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
struct hid_device_info* devs = hid_enumerate(HTC_ID, VIVE_HMD);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
int idx = 0;
|
||||
while (cur_dev) {
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD HTC Vive Driver");
|
||||
strcpy(desc->vendor, "HTC/Valve");
|
||||
strcpy(desc->product, "HTC Vive");
|
||||
|
||||
desc->revision = 0;
|
||||
|
||||
snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down HTC Vive driver");
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_htc_vive_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
|
||||
if(!drv)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
drv->ctx = ctx;
|
||||
|
||||
return drv;
|
||||
}
|
41
extern/openhmd/src/drv_htc_vive/vive.h
vendored
Normal file
41
extern/openhmd/src/drv_htc_vive/vive.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef VIVE_H
|
||||
#define VIVE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../openhmdi.h"
|
||||
#include "magic.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIVE_CONFIG_DATA = 17,
|
||||
VIVE_IRQ_SENSORS = 32,
|
||||
} vive_irq_cmd;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t acc[3];
|
||||
int16_t rot[3];
|
||||
uint32_t time_ticks;
|
||||
uint8_t seq;
|
||||
} vive_sensor_sample;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
vive_sensor_sample samples[3];
|
||||
} vive_sensor_packet;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
uint16_t length;
|
||||
unsigned char config_data[99999];
|
||||
} vive_config_packet;
|
||||
|
||||
void vec3f_from_vive_vec(const int16_t* smp, vec3f* out_vec);
|
||||
bool vive_decode_sensor_packet(vive_sensor_packet* pkt, const unsigned char* buffer, int size);
|
||||
bool vive_decode_config_packet(vive_config_packet* pkt, const unsigned char* buffer, int size);
|
||||
|
||||
#endif
|
275
extern/openhmd/src/drv_oculus_rift/packet.c
vendored
Normal file
275
extern/openhmd/src/drv_oculus_rift/packet.c
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Oculus Rift Driver - Packet Decoding and Utilities */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "rift.h"
|
||||
|
||||
#define SKIP_CMD (buffer++)
|
||||
#define READ8 *(buffer++);
|
||||
#define READ16 *buffer | (*(buffer + 1) << 8); buffer += 2;
|
||||
#define READ32 *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24); buffer += 4;
|
||||
#define READFLOAT ((float)(*buffer)); buffer += 4;
|
||||
#define READFIXED (float)(*buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24)) / 1000000.0f; buffer += 4;
|
||||
|
||||
#define WRITE8(_val) *(buffer++) = (_val);
|
||||
#define WRITE16(_val) WRITE8((_val) & 0xff); WRITE8(((_val) >> 8) & 0xff);
|
||||
#define WRITE32(_val) WRITE16((_val) & 0xffff) *buffer; WRITE16(((_val) >> 16) & 0xffff);
|
||||
|
||||
bool decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 8 || size == 9)){
|
||||
LOGE("invalid packet size (expected 8 or 9 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
range->command_id = READ16;
|
||||
range->accel_scale = READ8;
|
||||
range->gyro_scale = READ16;
|
||||
range->mag_scale = READ16;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 56 || size == 57)){
|
||||
LOGE("invalid packet size (expected 56 or 57 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
info->command_id = READ16;
|
||||
info->distortion_type = READ8;
|
||||
info->h_resolution = READ16;
|
||||
info->v_resolution = READ16;
|
||||
info->h_screen_size = READFIXED;
|
||||
info->v_screen_size = READFIXED;
|
||||
info->v_center = READFIXED;
|
||||
info->lens_separation = READFIXED;
|
||||
info->eye_to_screen_distance[0] = READFIXED;
|
||||
info->eye_to_screen_distance[1] = READFIXED;
|
||||
|
||||
info->distortion_type_opts = 0;
|
||||
|
||||
for(int i = 0; i < 6; i++){
|
||||
info->distortion_k[i] = READFLOAT;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 7 || size == 8)){
|
||||
LOGE("invalid packet size (expected 7 or 8 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
config->command_id = READ16;
|
||||
config->flags = READ8;
|
||||
config->packet_interval = READ8;
|
||||
config->keep_alive_interval = READ16;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void decode_sample(const unsigned char* buffer, int32_t* smp)
|
||||
{
|
||||
/*
|
||||
* Decode 3 tightly packed 21 bit values from 4 bytes.
|
||||
* We unpack them in the higher 21 bit values first and then shift
|
||||
* them down to the lower in order to get the sign bits correct.
|
||||
*/
|
||||
|
||||
int x = (buffer[0] << 24) | (buffer[1] << 16) | ((buffer[2] & 0xF8) << 8);
|
||||
int y = ((buffer[2] & 0x07) << 29) | (buffer[3] << 21) | (buffer[4] << 13) | ((buffer[5] & 0xC0) << 5);
|
||||
int z = ((buffer[5] & 0x3F) << 26) | (buffer[6] << 18) | (buffer[7] << 10);
|
||||
|
||||
smp[0] = x >> 11;
|
||||
smp[1] = y >> 11;
|
||||
smp[2] = z >> 11;
|
||||
}
|
||||
|
||||
bool decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 62 || size == 64)){
|
||||
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
msg->num_samples = READ8;
|
||||
msg->timestamp = READ16;
|
||||
msg->timestamp *= 1000; // DK1 timestamps are in milliseconds
|
||||
msg->last_command_id = READ16;
|
||||
msg->temperature = READ16;
|
||||
|
||||
msg->num_samples = OHMD_MIN(msg->num_samples, 3);
|
||||
for(int i = 0; i < msg->num_samples; i++){
|
||||
decode_sample(buffer, msg->samples[i].accel);
|
||||
buffer += 8;
|
||||
|
||||
decode_sample(buffer, msg->samples[i].gyro);
|
||||
buffer += 8;
|
||||
}
|
||||
|
||||
// Skip empty samples
|
||||
buffer += (3 - msg->num_samples) * 16;
|
||||
for(int i = 0; i < 3; i++){
|
||||
msg->mag[i] = READ16;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode_tracker_sensor_msg_dk2(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(!(size == 64)){
|
||||
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
SKIP_CMD;
|
||||
msg->last_command_id = READ16;
|
||||
msg->num_samples = READ8;
|
||||
/* Next is the number of samples since start, excluding the samples
|
||||
contained in this packet */
|
||||
buffer += 2; // unused: nb_samples_since_start
|
||||
msg->temperature = READ16;
|
||||
msg->timestamp = READ32;
|
||||
|
||||
/* Second sample value is junk (outdated/uninitialized) value if
|
||||
num_samples < 2. */
|
||||
msg->num_samples = OHMD_MIN(msg->num_samples, 2);
|
||||
for(int i = 0; i < msg->num_samples; i++){
|
||||
decode_sample(buffer, msg->samples[i].accel);
|
||||
buffer += 8;
|
||||
|
||||
decode_sample(buffer, msg->samples[i].gyro);
|
||||
buffer += 8;
|
||||
}
|
||||
|
||||
// Skip empty samples
|
||||
buffer += (2 - msg->num_samples) * 16;
|
||||
|
||||
for(int i = 0; i < 3; i++){
|
||||
msg->mag[i] = READ16;
|
||||
}
|
||||
|
||||
// TODO: positional tracking data and frame data
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO do we need to consider HMD vs sensor "centric" values
|
||||
void vec3f_from_rift_vec(const int32_t* smp, vec3f* out_vec)
|
||||
{
|
||||
out_vec->x = (float)smp[0] * 0.0001f;
|
||||
out_vec->y = (float)smp[1] * 0.0001f;
|
||||
out_vec->z = (float)smp[2] * 0.0001f;
|
||||
}
|
||||
|
||||
int encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config)
|
||||
{
|
||||
WRITE8(RIFT_CMD_SENSOR_CONFIG);
|
||||
WRITE16(config->command_id);
|
||||
WRITE8(config->flags);
|
||||
WRITE8(config->packet_interval);
|
||||
WRITE16(config->keep_alive_interval);
|
||||
return 7; // sensor config packet size
|
||||
}
|
||||
|
||||
int encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive)
|
||||
{
|
||||
WRITE8(RIFT_CMD_KEEP_ALIVE);
|
||||
WRITE16(keep_alive->command_id);
|
||||
WRITE16(keep_alive->keep_alive_interval);
|
||||
return 5; // keep alive packet size
|
||||
}
|
||||
|
||||
int encode_enable_components(unsigned char* buffer, bool display, bool audio)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
|
||||
WRITE8(RIFT_CMD_ENABLE_COMPONENTS);
|
||||
WRITE16(0); // last command ID
|
||||
|
||||
if (display)
|
||||
flags |= 1;
|
||||
if (audio)
|
||||
flags |= 2;
|
||||
// flags |= 4; // I don't know what it is. Wireless?
|
||||
WRITE8(flags);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void dump_packet_sensor_range(const pkt_sensor_range* range)
|
||||
{
|
||||
(void)range;
|
||||
|
||||
LOGD("sensor range\n");
|
||||
LOGD(" command id: %d", range->command_id);
|
||||
LOGD(" accel scale: %d", range->accel_scale);
|
||||
LOGD(" gyro scale: %d", range->gyro_scale);
|
||||
LOGD(" mag scale: %d", range->mag_scale);
|
||||
}
|
||||
|
||||
void dump_packet_sensor_display_info(const pkt_sensor_display_info* info)
|
||||
{
|
||||
(void)info;
|
||||
|
||||
LOGD("display info");
|
||||
LOGD(" command id: %d", info->command_id);
|
||||
LOGD(" distortion_type: %d", info->distortion_type);
|
||||
LOGD(" resolution: %d x %d", info->h_resolution, info->v_resolution);
|
||||
LOGD(" screen size: %f x %f", info->h_screen_size, info->v_screen_size);
|
||||
LOGD(" vertical center: %f", info->v_center);
|
||||
LOGD(" lens_separation: %f", info->lens_separation);
|
||||
LOGD(" eye_to_screen_distance: %f, %f", info->eye_to_screen_distance[0], info->eye_to_screen_distance[1]);
|
||||
LOGD(" distortion_k: %f, %f, %f, %f, %f, %f",
|
||||
info->distortion_k[0], info->distortion_k[1], info->distortion_k[2],
|
||||
info->distortion_k[3], info->distortion_k[4], info->distortion_k[5]);
|
||||
}
|
||||
|
||||
void dump_packet_sensor_config(const pkt_sensor_config* config)
|
||||
{
|
||||
(void)config;
|
||||
|
||||
LOGD("sensor config");
|
||||
LOGD(" command id: %u", config->command_id);
|
||||
LOGD(" flags: %02x", config->flags);
|
||||
LOGD(" raw mode: %d", !!(config->flags & RIFT_SCF_RAW_MODE));
|
||||
LOGD(" calibration test: %d", !!(config->flags & RIFT_SCF_CALIBRATION_TEST));
|
||||
LOGD(" use calibration: %d", !!(config->flags & RIFT_SCF_USE_CALIBRATION));
|
||||
LOGD(" auto calibration: %d", !!(config->flags & RIFT_SCF_AUTO_CALIBRATION));
|
||||
LOGD(" motion keep alive: %d", !!(config->flags & RIFT_SCF_MOTION_KEEP_ALIVE));
|
||||
LOGD(" motion command keep alive: %d", !!(config->flags & RIFT_SCF_COMMAND_KEEP_ALIVE));
|
||||
LOGD(" sensor coordinates: %d", !!(config->flags & RIFT_SCF_SENSOR_COORDINATES));
|
||||
LOGD(" packet interval: %u", config->packet_interval);
|
||||
LOGD(" keep alive interval: %u", config->keep_alive_interval);
|
||||
}
|
||||
|
||||
void dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor)
|
||||
{
|
||||
(void)sensor;
|
||||
|
||||
LOGD("tracker sensor:");
|
||||
LOGD(" last command id: %u", sensor->last_command_id);
|
||||
LOGD(" timestamp: %u", sensor->timestamp);
|
||||
LOGD(" temperature: %d", sensor->temperature);
|
||||
LOGD(" num samples: %u", sensor->num_samples);
|
||||
LOGD(" magnetic field: %i %i %i", sensor->mag[0], sensor->mag[1], sensor->mag[2]);
|
||||
|
||||
for(int i = 0; i < sensor->num_samples; i++){
|
||||
LOGD(" accel: %d %d %d", sensor->samples[i].accel[0], sensor->samples[i].accel[1], sensor->samples[i].accel[2]);
|
||||
LOGD(" gyro: %d %d %d", sensor->samples[i].gyro[0], sensor->samples[i].gyro[1], sensor->samples[i].gyro[2]);
|
||||
}
|
||||
}
|
456
extern/openhmd/src/drv_oculus_rift/rift.c
vendored
Normal file
456
extern/openhmd/src/drv_oculus_rift/rift.c
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Oculus Rift Driver - HID/USB Driver Implementation */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <hidapi.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "rift.h"
|
||||
|
||||
#define TICK_LEN (1.0f / 1000.0f) // 1000 Hz ticks
|
||||
#define KEEP_ALIVE_VALUE (10 * 1000)
|
||||
#define SETFLAG(_s, _flag, _val) (_s) = ((_s) & ~(_flag)) | ((_val) ? (_flag) : 0)
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
|
||||
hid_device* handle;
|
||||
pkt_sensor_range sensor_range;
|
||||
pkt_sensor_display_info display_info;
|
||||
rift_coordinate_frame coordinate_frame, hw_coordinate_frame;
|
||||
pkt_sensor_config sensor_config;
|
||||
pkt_tracker_sensor sensor;
|
||||
uint32_t last_imu_timestamp;
|
||||
double last_keep_alive;
|
||||
fusion sensor_fusion;
|
||||
vec3f raw_mag, raw_accel, raw_gyro;
|
||||
} rift_priv;
|
||||
|
||||
typedef enum {
|
||||
REV_DK1,
|
||||
REV_DK2,
|
||||
REV_CV1
|
||||
} rift_revision;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
int id;
|
||||
int iface;
|
||||
rift_revision rev;
|
||||
} rift_devices;
|
||||
|
||||
static rift_priv* rift_priv_get(ohmd_device* device)
|
||||
{
|
||||
return (rift_priv*)device;
|
||||
}
|
||||
|
||||
static int get_feature_report(rift_priv* priv, rift_sensor_feature_cmd cmd, unsigned char* buf)
|
||||
{
|
||||
memset(buf, 0, FEATURE_BUFFER_SIZE);
|
||||
buf[0] = (unsigned char)cmd;
|
||||
return hid_get_feature_report(priv->handle, buf, FEATURE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static int send_feature_report(rift_priv* priv, const unsigned char *data, size_t length)
|
||||
{
|
||||
return hid_send_feature_report(priv->handle, data, length);
|
||||
}
|
||||
|
||||
static void set_coordinate_frame(rift_priv* priv, rift_coordinate_frame coordframe)
|
||||
{
|
||||
priv->coordinate_frame = coordframe;
|
||||
|
||||
// set the RIFT_SCF_SENSOR_COORDINATES in the sensor config to match whether coordframe is hmd or sensor
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_SENSOR_COORDINATES, coordframe == RIFT_CF_SENSOR);
|
||||
|
||||
// encode send the new config to the Rift
|
||||
unsigned char buf[FEATURE_BUFFER_SIZE];
|
||||
int size = encode_sensor_config(buf, &priv->sensor_config);
|
||||
if(send_feature_report(priv, buf, size) == -1){
|
||||
ohmd_set_error(priv->base.ctx, "send_feature_report failed in set_coordinate frame");
|
||||
return;
|
||||
}
|
||||
|
||||
// read the state again, set the hw_coordinate_frame to match what
|
||||
// the hardware actually is set to just incase it doesn't stick.
|
||||
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
|
||||
if(size <= 0){
|
||||
LOGW("could not set coordinate frame");
|
||||
priv->hw_coordinate_frame = RIFT_CF_HMD;
|
||||
return;
|
||||
}
|
||||
|
||||
decode_sensor_config(&priv->sensor_config, buf, size);
|
||||
priv->hw_coordinate_frame = (priv->sensor_config.flags & RIFT_SCF_SENSOR_COORDINATES) ? RIFT_CF_SENSOR : RIFT_CF_HMD;
|
||||
|
||||
if(priv->hw_coordinate_frame != coordframe) {
|
||||
LOGW("coordinate frame didn't stick");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tracker_sensor_msg(rift_priv* priv, unsigned char* buffer, int size)
|
||||
{
|
||||
if (buffer[0] == RIFT_IRQ_SENSORS
|
||||
&& !decode_tracker_sensor_msg(&priv->sensor, buffer, size)){
|
||||
LOGE("couldn't decode tracker sensor message");
|
||||
}
|
||||
|
||||
if (buffer[0] == RIFT_IRQ_SENSORS_DK2
|
||||
&& !decode_tracker_sensor_msg_dk2(&priv->sensor, buffer, size)){
|
||||
LOGE("couldn't decode tracker sensor message");
|
||||
}
|
||||
|
||||
pkt_tracker_sensor* s = &priv->sensor;
|
||||
|
||||
dump_packet_tracker_sensor(s);
|
||||
|
||||
int32_t mag32[] = { s->mag[0], s->mag[1], s->mag[2] };
|
||||
vec3f_from_rift_vec(mag32, &priv->raw_mag);
|
||||
|
||||
// TODO: handle overflows in a nicer way
|
||||
float dt = TICK_LEN; // TODO: query the Rift for the sample rate
|
||||
if (s->timestamp > priv->last_imu_timestamp)
|
||||
{
|
||||
dt = (s->timestamp - priv->last_imu_timestamp) / 1000000.0f;
|
||||
dt -= (s->num_samples - 1) * TICK_LEN; // TODO: query the Rift for the sample rate
|
||||
}
|
||||
|
||||
for(int i = 0; i < s->num_samples; i++){
|
||||
vec3f_from_rift_vec(s->samples[i].accel, &priv->raw_accel);
|
||||
vec3f_from_rift_vec(s->samples[i].gyro, &priv->raw_gyro);
|
||||
|
||||
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &priv->raw_mag);
|
||||
dt = TICK_LEN; // TODO: query the Rift for the sample rate
|
||||
}
|
||||
|
||||
priv->last_imu_timestamp = s->timestamp;
|
||||
}
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
unsigned char buffer[FEATURE_BUFFER_SIZE];
|
||||
|
||||
// Handle keep alive messages
|
||||
double t = ohmd_get_tick();
|
||||
if(t - priv->last_keep_alive >= (double)priv->sensor_config.keep_alive_interval / 1000.0 - .2){
|
||||
// send keep alive message
|
||||
pkt_keep_alive keep_alive = { 0, priv->sensor_config.keep_alive_interval };
|
||||
int ka_size = encode_keep_alive(buffer, &keep_alive);
|
||||
if (send_feature_report(priv, buffer, ka_size) == -1)
|
||||
LOGE("error sending keepalive");
|
||||
|
||||
// Update the time of the last keep alive we have sent.
|
||||
priv->last_keep_alive = t;
|
||||
}
|
||||
|
||||
// Read all the messages from the device.
|
||||
while(true){
|
||||
int size = hid_read(priv->handle, buffer, FEATURE_BUFFER_SIZE);
|
||||
if(size < 0){
|
||||
LOGE("error reading from device");
|
||||
return;
|
||||
} else if(size == 0) {
|
||||
return; // No more messages, return.
|
||||
}
|
||||
|
||||
// currently the only message type the hardware supports (I think)
|
||||
if(buffer[0] == RIFT_IRQ_SENSORS || buffer[0] == RIFT_IRQ_SENSORS_DK2) {
|
||||
handle_tracker_sensor_msg(priv, buffer, size);
|
||||
}else{
|
||||
LOGE("unknown message type: %u", buffer[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
|
||||
switch(type){
|
||||
case OHMD_DISTORTION_K: {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
out[i] = priv->display_info.distortion_k[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_ROTATION_QUAT: {
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
}
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
LOGD("closing device");
|
||||
rift_priv* priv = rift_priv_get(device);
|
||||
hid_close(priv->handle);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static char* _hid_to_unix_path(char* path)
|
||||
{
|
||||
char bus [4];
|
||||
char dev [4];
|
||||
char *result = malloc( sizeof(char) * ( 20 + 1 ) );
|
||||
|
||||
sprintf (bus, "%.*s\n", 4, path);
|
||||
sprintf (dev, "%.*s\n", 4, path + 5);
|
||||
|
||||
sprintf (result, "/dev/bus/usb/%03d/%03d",
|
||||
(int)strtol(bus, NULL, 16),
|
||||
(int)strtol(dev, NULL, 16));
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static char* _hid_to_unix_path(char* path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
rift_priv* priv = ohmd_alloc(driver->ctx, sizeof(rift_priv));
|
||||
if(!priv)
|
||||
goto cleanup;
|
||||
|
||||
priv->last_imu_timestamp = -1;
|
||||
|
||||
priv->base.ctx = driver->ctx;
|
||||
|
||||
ohmd_toggle_ovr_service(0); //disable OVRService if running
|
||||
|
||||
// Open the HID device
|
||||
priv->handle = hid_open_path(desc->path);
|
||||
|
||||
if(!priv->handle) {
|
||||
char* path = _hid_to_unix_path(desc->path);
|
||||
ohmd_set_error(driver->ctx, "Could not open %s. "
|
||||
"Check your rights.", path);
|
||||
#ifndef _MSC_VER
|
||||
free(path);
|
||||
#endif
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(hid_set_nonblocking(priv->handle, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
unsigned char buf[FEATURE_BUFFER_SIZE];
|
||||
|
||||
int size;
|
||||
|
||||
// Read and decode the sensor range
|
||||
size = get_feature_report(priv, RIFT_CMD_RANGE, buf);
|
||||
decode_sensor_range(&priv->sensor_range, buf, size);
|
||||
dump_packet_sensor_range(&priv->sensor_range);
|
||||
|
||||
// Read and decode display information
|
||||
size = get_feature_report(priv, RIFT_CMD_DISPLAY_INFO, buf);
|
||||
decode_sensor_display_info(&priv->display_info, buf, size);
|
||||
dump_packet_sensor_display_info(&priv->display_info);
|
||||
|
||||
// Read and decode the sensor config
|
||||
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
|
||||
decode_sensor_config(&priv->sensor_config, buf, size);
|
||||
dump_packet_sensor_config(&priv->sensor_config);
|
||||
|
||||
// if the sensor has display info data, use HMD coordinate frame
|
||||
priv->coordinate_frame = priv->display_info.distortion_type != RIFT_DT_NONE ? RIFT_CF_HMD : RIFT_CF_SENSOR;
|
||||
|
||||
// enable calibration
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_USE_CALIBRATION, 1);
|
||||
SETFLAG(priv->sensor_config.flags, RIFT_SCF_AUTO_CALIBRATION, 1);
|
||||
|
||||
// apply sensor config
|
||||
set_coordinate_frame(priv, priv->coordinate_frame);
|
||||
|
||||
// Turn the screens on
|
||||
if (desc->revision == REV_CV1)
|
||||
{
|
||||
size = encode_enable_components(buf, true, true);
|
||||
if (send_feature_report(priv, buf, size) == -1)
|
||||
LOGE("error turning the screens on");
|
||||
}
|
||||
|
||||
// set keep alive interval to n seconds
|
||||
pkt_keep_alive keep_alive = { 0, KEEP_ALIVE_VALUE };
|
||||
size = encode_keep_alive(buf, &keep_alive);
|
||||
if (send_feature_report(priv, buf, size) == -1)
|
||||
LOGE("error setting up keepalive");
|
||||
|
||||
// Update the time of the last keep alive we have sent.
|
||||
priv->last_keep_alive = ohmd_get_tick();
|
||||
|
||||
// update sensor settings with new keep alive value
|
||||
// (which will have been ignored in favor of the default 1000 ms one)
|
||||
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
|
||||
decode_sensor_config(&priv->sensor_config, buf, size);
|
||||
dump_packet_sensor_config(&priv->sensor_config);
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties
|
||||
priv->base.properties.hsize = priv->display_info.h_screen_size;
|
||||
priv->base.properties.vsize = priv->display_info.v_screen_size;
|
||||
priv->base.properties.hres = priv->display_info.h_resolution;
|
||||
priv->base.properties.vres = priv->display_info.v_resolution;
|
||||
priv->base.properties.lens_sep = priv->display_info.lens_separation;
|
||||
priv->base.properties.lens_vpos = priv->display_info.v_center;
|
||||
priv->base.properties.ratio = ((float)priv->display_info.h_resolution / (float)priv->display_info.v_resolution) / 2.0f;
|
||||
|
||||
//setup generic distortion coeffs, from hand-calibration
|
||||
switch (desc->revision) {
|
||||
case REV_DK2:
|
||||
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.247, -0.145, 0.103, 0.795);
|
||||
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.985, 1.000, 1.015);
|
||||
break;
|
||||
case REV_DK1:
|
||||
ohmd_set_universal_distortion_k(&(priv->base.properties), 1.003, -1.005, 0.403, 0.599);
|
||||
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.985, 1.000, 1.015);
|
||||
break;
|
||||
case REV_CV1:
|
||||
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.098, .324, -0.241, 0.819);
|
||||
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.9952420, 1.0, 1.0008074);
|
||||
/* CV1 reports IPD, but not lens center, at least not anywhere I could find, so use the manually measured value of 0.054 */
|
||||
priv->display_info.lens_separation = 0.054;
|
||||
priv->base.properties.lens_sep = priv->display_info.lens_separation;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
//ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
float l,r,t,b,n,f;
|
||||
// left eye screen bounds
|
||||
l = -1.0f * (priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2);
|
||||
r = priv->display_info.lens_separation/2;
|
||||
t = priv->display_info.v_screen_size - priv->display_info.v_center;
|
||||
b = -1.0f * priv->display_info.v_center;
|
||||
n = priv->display_info.eye_to_screen_distance[0];
|
||||
f = n*10e6;
|
||||
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
|
||||
/* eye separation is handled by IPD in the Modelview matrix */
|
||||
omat4x4f_init_frustum(&priv->base.properties.proj_left, l, r, b, t, n, f);
|
||||
//right eye screen bounds
|
||||
l = -1.0f * priv->display_info.lens_separation/2;
|
||||
r = priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2;
|
||||
n = priv->display_info.eye_to_screen_distance[1];
|
||||
f = n*10e6;
|
||||
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
|
||||
/* eye separation is handled by IPD in the Modelview matrix */
|
||||
omat4x4f_init_frustum(&priv->base.properties.proj_right, l, r, b, t, n, f);
|
||||
|
||||
priv->base.properties.fov = 2 * atan2f(
|
||||
priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2,
|
||||
priv->display_info.eye_to_screen_distance[0]);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
|
||||
// initialize sensor fusion
|
||||
ofusion_init(&priv->sensor_fusion);
|
||||
|
||||
return &priv->base;
|
||||
|
||||
cleanup:
|
||||
if(priv)
|
||||
free(priv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define OCULUS_VR_INC_ID 0x2833
|
||||
#define RIFT_ID_COUNT 4
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
// enumerate HID devices and add any Rifts found to the device list
|
||||
|
||||
rift_devices rd[RIFT_ID_COUNT] = {
|
||||
{ "Rift (DK1)", 0x0001, -1, REV_DK1 },
|
||||
{ "Rift (DK2)", 0x0021, -1, REV_DK2 },
|
||||
{ "Rift (DK2)", 0x2021, -1, REV_DK2 },
|
||||
{ "Rift (CV1)", 0x0031, 0, REV_CV1 },
|
||||
};
|
||||
|
||||
for(int i = 0; i < RIFT_ID_COUNT; i++){
|
||||
struct hid_device_info* devs = hid_enumerate(OCULUS_VR_INC_ID, rd[i].id);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
if(devs == NULL)
|
||||
continue;
|
||||
|
||||
while (cur_dev) {
|
||||
if(rd[i].iface == -1 || cur_dev->interface_number == rd[i].iface){
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD Rift Driver");
|
||||
strcpy(desc->vendor, "Oculus VR, Inc.");
|
||||
strcpy(desc->product, rd[i].name);
|
||||
|
||||
desc->revision = rd[i].rev;
|
||||
|
||||
strcpy(desc->path, cur_dev->path);
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
}
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down driver");
|
||||
hid_exit();
|
||||
free(drv);
|
||||
|
||||
ohmd_toggle_ovr_service(1); //re-enable OVRService if previously running
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_oculus_rift_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
if(drv == NULL)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
drv->ctx = ctx;
|
||||
|
||||
return drv;
|
||||
}
|
115
extern/openhmd/src/drv_oculus_rift/rift.h
vendored
Normal file
115
extern/openhmd/src/drv_oculus_rift/rift.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Oculus Rift Driver Internal Interface */
|
||||
|
||||
#ifndef RIFT_H
|
||||
#define RIFT_H
|
||||
|
||||
#include "../openhmdi.h"
|
||||
|
||||
#define FEATURE_BUFFER_SIZE 256
|
||||
|
||||
typedef enum {
|
||||
RIFT_CMD_SENSOR_CONFIG = 2,
|
||||
RIFT_CMD_RANGE = 4,
|
||||
RIFT_CMD_KEEP_ALIVE = 8,
|
||||
RIFT_CMD_DISPLAY_INFO = 9,
|
||||
RIFT_CMD_ENABLE_COMPONENTS = 0x1d
|
||||
} rift_sensor_feature_cmd;
|
||||
|
||||
typedef enum {
|
||||
RIFT_CF_SENSOR,
|
||||
RIFT_CF_HMD
|
||||
} rift_coordinate_frame;
|
||||
|
||||
typedef enum {
|
||||
RIFT_IRQ_SENSORS = 1,
|
||||
RIFT_IRQ_SENSORS_DK2 = 11
|
||||
} rift_irq_cmd;
|
||||
|
||||
typedef enum {
|
||||
RIFT_DT_NONE,
|
||||
RIFT_DT_SCREEN_ONLY,
|
||||
RIFT_DT_DISTORTION
|
||||
} rift_distortion_type;
|
||||
|
||||
// Sensor config flags
|
||||
#define RIFT_SCF_RAW_MODE 0x01
|
||||
#define RIFT_SCF_CALIBRATION_TEST 0x02
|
||||
#define RIFT_SCF_USE_CALIBRATION 0x04
|
||||
#define RIFT_SCF_AUTO_CALIBRATION 0x08
|
||||
#define RIFT_SCF_MOTION_KEEP_ALIVE 0x10
|
||||
#define RIFT_SCF_COMMAND_KEEP_ALIVE 0x20
|
||||
#define RIFT_SCF_SENSOR_COORDINATES 0x40
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint16_t accel_scale;
|
||||
uint16_t gyro_scale;
|
||||
uint16_t mag_scale;
|
||||
} pkt_sensor_range;
|
||||
|
||||
typedef struct {
|
||||
int32_t accel[3];
|
||||
int32_t gyro[3];
|
||||
} pkt_tracker_sample;
|
||||
|
||||
typedef struct {
|
||||
uint8_t num_samples;
|
||||
uint32_t timestamp;
|
||||
uint16_t last_command_id;
|
||||
int16_t temperature;
|
||||
pkt_tracker_sample samples[3];
|
||||
int16_t mag[3];
|
||||
} pkt_tracker_sensor;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint8_t flags;
|
||||
uint16_t packet_interval;
|
||||
uint16_t keep_alive_interval; // in ms
|
||||
} pkt_sensor_config;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
rift_distortion_type distortion_type;
|
||||
uint8_t distortion_type_opts;
|
||||
uint16_t h_resolution, v_resolution;
|
||||
float h_screen_size, v_screen_size;
|
||||
float v_center;
|
||||
float lens_separation;
|
||||
float eye_to_screen_distance[2];
|
||||
float distortion_k[6];
|
||||
} pkt_sensor_display_info;
|
||||
|
||||
typedef struct {
|
||||
uint16_t command_id;
|
||||
uint16_t keep_alive_interval;
|
||||
} pkt_keep_alive;
|
||||
|
||||
|
||||
bool decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size);
|
||||
bool decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size);
|
||||
bool decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size);
|
||||
bool decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
|
||||
bool decode_tracker_sensor_msg_dk2(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
|
||||
|
||||
void vec3f_from_rift_vec(const int32_t* smp, vec3f* out_vec);
|
||||
|
||||
int encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config);
|
||||
int encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive);
|
||||
int encode_enable_components(unsigned char* buffer, bool display, bool audio);
|
||||
|
||||
void dump_packet_sensor_range(const pkt_sensor_range* range);
|
||||
void dump_packet_sensor_config(const pkt_sensor_config* config);
|
||||
void dump_packet_sensor_display_info(const pkt_sensor_display_info* info);
|
||||
void dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor);
|
||||
|
||||
#endif
|
53
extern/openhmd/src/drv_psvr/packet.c
vendored
Normal file
53
extern/openhmd/src/drv_psvr/packet.c
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "psvr.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
inline static uint8_t read8(const unsigned char** buffer)
|
||||
{
|
||||
uint8_t ret = **buffer;
|
||||
*buffer += 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static int16_t read16(const unsigned char** buffer)
|
||||
{
|
||||
int16_t ret = **buffer | (*(*buffer + 1) << 8);
|
||||
*buffer += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static uint32_t read32(const unsigned char** buffer)
|
||||
{
|
||||
uint32_t ret = **buffer | (*(*buffer + 1) << 8) | (*(*buffer + 2) << 16) | (*(*buffer + 3) << 24);
|
||||
*buffer += 4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool psvr_decode_sensor_packet(psvr_sensor_packet* pkt, const unsigned char* buffer, int size)
|
||||
{
|
||||
if(size != 64){
|
||||
LOGE("invalid psvr sensor packet size (expected 64 but got %d)", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer += 2; //skip 2
|
||||
pkt->samples[0].volume = read16(&buffer); //volume
|
||||
buffer += 12; //unknown, skip 12
|
||||
pkt->samples[0].tick = read32(&buffer); //TICK
|
||||
// acceleration
|
||||
for(int i = 0; i < 3; i++){
|
||||
pkt->samples[0].gyro[i] = read16(&buffer);
|
||||
}
|
||||
|
||||
// rotation
|
||||
for(int i = 0; i < 3; i++){
|
||||
pkt->samples[0].accel[i] = read16(&buffer);
|
||||
}//34
|
||||
buffer += 23; //probably other sample somewhere
|
||||
pkt->samples[0].proximity = read8(&buffer); //255 for close
|
||||
pkt->samples[0].proximity_state = read8(&buffer); // 0 (nothing) to 3 (headset is on)
|
||||
|
||||
return true;
|
||||
}
|
296
extern/openhmd/src/drv_psvr/psvr.c
vendored
Normal file
296
extern/openhmd/src/drv_psvr/psvr.c
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Sony PSVR Driver */
|
||||
|
||||
#define FEATURE_BUFFER_SIZE 256
|
||||
|
||||
#define TICK_LEN (1.0f / 1000000.0f) // 1000 Hz ticks
|
||||
|
||||
#define SONY_ID 0x054c
|
||||
#define PSVR_HMD 0x09af
|
||||
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <hidapi.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "psvr.h"
|
||||
|
||||
typedef struct {
|
||||
ohmd_device base;
|
||||
|
||||
hid_device* hmd_handle;
|
||||
hid_device* hmd_control;
|
||||
fusion sensor_fusion;
|
||||
vec3f raw_accel, raw_gyro;
|
||||
uint32_t last_ticks;
|
||||
uint8_t last_seq;
|
||||
psvr_sensor_packet sensor;
|
||||
|
||||
} psvr_priv;
|
||||
|
||||
void vec3f_from_psvr_vec(const int16_t* smp, vec3f* out_vec)
|
||||
{
|
||||
out_vec->x = (float)smp[1] * 0.001f;
|
||||
out_vec->y = (float)smp[0] * 0.001f;
|
||||
out_vec->z = (float)smp[2] * 0.001f * -1.0f;
|
||||
}
|
||||
|
||||
static void handle_tracker_sensor_msg(psvr_priv* priv, unsigned char* buffer, int size)
|
||||
{
|
||||
uint32_t last_sample_tick = priv->sensor.tick;
|
||||
|
||||
if(!psvr_decode_sensor_packet(&priv->sensor, buffer, size)){
|
||||
LOGE("couldn't decode tracker sensor message");
|
||||
}
|
||||
|
||||
psvr_sensor_packet* s = &priv->sensor;
|
||||
|
||||
uint32_t tick_delta = 1000;
|
||||
if(last_sample_tick > 0) //startup correction
|
||||
tick_delta = s->tick - last_sample_tick;
|
||||
|
||||
float dt = tick_delta * TICK_LEN;
|
||||
vec3f mag = {{0.0f, 0.0f, 0.0f}};
|
||||
|
||||
for(int i = 0; i < 1; i++){ //just use 1 sample since we don't have sample order for frame
|
||||
vec3f_from_psvr_vec(s->samples[i].accel, &priv->raw_accel);
|
||||
vec3f_from_psvr_vec(s->samples[i].gyro, &priv->raw_gyro);
|
||||
|
||||
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &mag);
|
||||
|
||||
// reset dt to tick_len for the last samples if there were more than one sample
|
||||
dt = TICK_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_device(ohmd_device* device)
|
||||
{
|
||||
psvr_priv* priv = (psvr_priv*)device;
|
||||
|
||||
int size = 0;
|
||||
unsigned char buffer[FEATURE_BUFFER_SIZE];
|
||||
|
||||
while(true){
|
||||
int size = hid_read(priv->hmd_handle, buffer, FEATURE_BUFFER_SIZE);
|
||||
if(size < 0){
|
||||
LOGE("error reading from device");
|
||||
return;
|
||||
} else if(size == 0) {
|
||||
return; // No more messages, return.
|
||||
}
|
||||
|
||||
// currently the only message type the hardware supports (I think)
|
||||
if(buffer[0] == PSVR_IRQ_SENSORS){
|
||||
handle_tracker_sensor_msg(priv, buffer, size);
|
||||
}else if (buffer[0] == PSVR_IRQ_VOLUME_PLUS){
|
||||
//TODO implement
|
||||
}else if (buffer[0] == PSVR_IRQ_VOLUME_MINUS){
|
||||
//TODO implement
|
||||
}else if (buffer[0] == PSVR_IRQ_MIC_MUTE){
|
||||
//TODO implement
|
||||
}else{
|
||||
LOGE("unknown message type: %u", buffer[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if(size < 0){
|
||||
LOGE("error reading from device");
|
||||
}
|
||||
}
|
||||
|
||||
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
psvr_priv* priv = (psvr_priv*)device;
|
||||
|
||||
switch(type){
|
||||
case OHMD_ROTATION_QUAT:
|
||||
*(quatf*)out = priv->sensor_fusion.orient;
|
||||
break;
|
||||
|
||||
case OHMD_POSITION_VECTOR:
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
break;
|
||||
|
||||
case OHMD_DISTORTION_K:
|
||||
// TODO this should be set to the equivalent of no distortion
|
||||
memset(out, 0, sizeof(float) * 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_device(ohmd_device* device)
|
||||
{
|
||||
psvr_priv* priv = (psvr_priv*)device;
|
||||
|
||||
LOGD("closing HTC PSVR device");
|
||||
|
||||
hid_close(priv->hmd_handle);
|
||||
hid_close(priv->hmd_control);
|
||||
|
||||
free(device);
|
||||
}
|
||||
|
||||
static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
|
||||
{
|
||||
struct hid_device_info* devs = hid_enumerate(manufacturer, product);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
int idx = 0;
|
||||
int iface_cur = 0;
|
||||
hid_device* ret = NULL;
|
||||
|
||||
while (cur_dev) {
|
||||
printf("%04x:%04x %s\n", (unsigned int)manufacturer, (unsigned int)product, cur_dev->path);
|
||||
|
||||
if(idx == device_index && iface == iface_cur){
|
||||
ret = hid_open_path(cur_dev->path);
|
||||
printf("opening\n");
|
||||
}
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
|
||||
iface_cur++;
|
||||
|
||||
if(iface_cur >= iface_tot){
|
||||
idx++;
|
||||
iface_cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
|
||||
{
|
||||
psvr_priv* priv = ohmd_alloc(driver->ctx, sizeof(psvr_priv));
|
||||
|
||||
if(!priv)
|
||||
return NULL;
|
||||
|
||||
priv->base.ctx = driver->ctx;
|
||||
|
||||
int idx = atoi(desc->path);
|
||||
|
||||
// Open the HMD device
|
||||
priv->hmd_handle = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, idx);
|
||||
|
||||
if(!priv->hmd_handle)
|
||||
goto cleanup;
|
||||
|
||||
if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Open the HMD Control device
|
||||
priv->hmd_control = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, 1);
|
||||
|
||||
if(!priv->hmd_control)
|
||||
goto cleanup;
|
||||
|
||||
if(hid_set_nonblocking(priv->hmd_control, 1) == -1){
|
||||
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// turn the display on
|
||||
hid_write(priv->hmd_control, psvr_power_on, sizeof(psvr_power_on));
|
||||
// set VR mode for the hmd
|
||||
hid_write(priv->hmd_control, psvr_vrmode_on, sizeof(psvr_vrmode_on));
|
||||
|
||||
// Set default device properties
|
||||
ohmd_set_default_device_properties(&priv->base.properties);
|
||||
|
||||
// Set device properties TODO: Get from device
|
||||
priv->base.properties.hsize = 0.126; //from calculated specs
|
||||
priv->base.properties.vsize = 0.071; //from calculated specs
|
||||
priv->base.properties.hres = 1920;
|
||||
priv->base.properties.vres = 1080;
|
||||
priv->base.properties.lens_sep = 0.063500;
|
||||
priv->base.properties.lens_vpos = 0.049694;
|
||||
priv->base.properties.fov = DEG_TO_RAD(103.57f); //TODO: Confirm exact mesurements
|
||||
priv->base.properties.ratio = (1920.0f / 1080.0f) / 2.0f;
|
||||
|
||||
// calculate projection eye projection matrices from the device properties
|
||||
ohmd_calc_default_proj_matrices(&priv->base.properties);
|
||||
|
||||
// set up device callbacks
|
||||
priv->base.update = update_device;
|
||||
priv->base.close = close_device;
|
||||
priv->base.getf = getf;
|
||||
|
||||
ofusion_init(&priv->sensor_fusion);
|
||||
|
||||
return (ohmd_device*)priv;
|
||||
|
||||
cleanup:
|
||||
if(priv)
|
||||
free(priv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
|
||||
{
|
||||
struct hid_device_info* devs = hid_enumerate(SONY_ID, PSVR_HMD);
|
||||
struct hid_device_info* cur_dev = devs;
|
||||
|
||||
int idx = 0;
|
||||
while (cur_dev) {
|
||||
ohmd_device_desc* desc = &list->devices[list->num_devices++];
|
||||
|
||||
strcpy(desc->driver, "OpenHMD Sony PSVR Driver");
|
||||
strcpy(desc->vendor, "Sony");
|
||||
strcpy(desc->product, "PSVR");
|
||||
|
||||
desc->revision = 0;
|
||||
|
||||
snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
|
||||
|
||||
desc->driver_ptr = driver;
|
||||
|
||||
cur_dev = cur_dev->next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
}
|
||||
|
||||
static void destroy_driver(ohmd_driver* drv)
|
||||
{
|
||||
LOGD("shutting down Sony PSVR driver");
|
||||
free(drv);
|
||||
}
|
||||
|
||||
ohmd_driver* ohmd_create_psvr_drv(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
|
||||
|
||||
if(!drv)
|
||||
return NULL;
|
||||
|
||||
drv->get_device_list = get_device_list;
|
||||
drv->open_device = open_device;
|
||||
drv->destroy = destroy_driver;
|
||||
drv->ctx = ctx;
|
||||
|
||||
return drv;
|
||||
}
|
48
extern/openhmd/src/drv_psvr/psvr.h
vendored
Normal file
48
extern/openhmd/src/drv_psvr/psvr.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef PSVR_H
|
||||
#define PSVR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../openhmdi.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PSVR_IRQ_SENSORS = 0,
|
||||
PSVR_IRQ_VOLUME_PLUS = 2,
|
||||
PSVR_IRQ_VOLUME_MINUS = 4,
|
||||
PSVR_IRQ_MIC_MUTE = 8
|
||||
} psvr_irq_cmd;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t accel[3];
|
||||
int16_t gyro[3];
|
||||
uint32_t tick;
|
||||
uint8_t seq;
|
||||
uint8_t volume;
|
||||
uint8_t proximity;
|
||||
uint8_t proximity_state;
|
||||
} psvr_sensor_sample;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
uint32_t tick;
|
||||
psvr_sensor_sample samples[1];
|
||||
} psvr_sensor_packet;
|
||||
|
||||
static const unsigned char psvr_vrmode_on[12] = {
|
||||
0x11, 0x00, 0xaa, 0x08, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
static const unsigned char psvr_power_on[8] = {
|
||||
0x17, 0x76, 0xaa, 0x04, 0x01, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
void vec3f_from_psvr_vec(const int16_t* smp, vec3f* out_vec);
|
||||
bool psvr_decode_sensor_packet(psvr_sensor_packet* pkt, const unsigned char* buffer, int size);
|
||||
|
||||
#endif
|
126
extern/openhmd/src/fusion.c
vendored
Normal file
126
extern/openhmd/src/fusion.c
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Sensor Fusion Implementation */
|
||||
|
||||
#include <string.h>
|
||||
#include "openhmdi.h"
|
||||
|
||||
void ofusion_init(fusion* me)
|
||||
{
|
||||
memset(me, 0, sizeof(fusion));
|
||||
me->orient.w = 1.0f;
|
||||
|
||||
ofq_init(&me->mag_fq, 20);
|
||||
ofq_init(&me->accel_fq, 20);
|
||||
ofq_init(&me->ang_vel_fq, 20);
|
||||
|
||||
me->flags = FF_USE_GRAVITY;
|
||||
me->grav_gain = 0.05f;
|
||||
}
|
||||
|
||||
void ofusion_update(fusion* me, float dt, const vec3f* ang_vel, const vec3f* accel, const vec3f* mag)
|
||||
{
|
||||
me->ang_vel = *ang_vel;
|
||||
me->accel = *accel;
|
||||
me->raw_mag = *mag;
|
||||
|
||||
me->mag = *mag;
|
||||
|
||||
vec3f world_accel;
|
||||
oquatf_get_rotated(&me->orient, accel, &world_accel);
|
||||
|
||||
me->iterations += 1;
|
||||
me->time += dt;
|
||||
|
||||
ofq_add(&me->mag_fq, mag);
|
||||
ofq_add(&me->accel_fq, &world_accel);
|
||||
ofq_add(&me->ang_vel_fq, ang_vel);
|
||||
|
||||
float ang_vel_length = ovec3f_get_length(ang_vel);
|
||||
|
||||
if(ang_vel_length > 0.0001f){
|
||||
vec3f rot_axis =
|
||||
{{ ang_vel->x / ang_vel_length, ang_vel->y / ang_vel_length, ang_vel->z / ang_vel_length }};
|
||||
|
||||
float rot_angle = ang_vel_length * dt;
|
||||
|
||||
quatf delta_orient;
|
||||
oquatf_init_axis(&delta_orient, &rot_axis, rot_angle);
|
||||
|
||||
oquatf_mult_me(&me->orient, &delta_orient);
|
||||
}
|
||||
|
||||
// gravity correction
|
||||
if(me->flags & FF_USE_GRAVITY){
|
||||
const float gravity_tolerance = .4f, ang_vel_tolerance = .1f;
|
||||
const float min_tilt_error = 0.05f, max_tilt_error = 0.01f;
|
||||
|
||||
// if the device is within tolerance levels, count this as the device is level and add to the counter
|
||||
// otherwise reset the counter and start over
|
||||
|
||||
me->device_level_count =
|
||||
fabsf(ovec3f_get_length(accel) - 9.82f) < gravity_tolerance * 2.0f && ang_vel_length < ang_vel_tolerance
|
||||
? me->device_level_count + 1 : 0;
|
||||
|
||||
// device has been level for long enough, grab mean from the accelerometer filter queue (last n values)
|
||||
// and use for correction
|
||||
|
||||
if(me->device_level_count > 50){
|
||||
me->device_level_count = 0;
|
||||
|
||||
vec3f accel_mean;
|
||||
ofq_get_mean(&me->accel_fq, &accel_mean);
|
||||
if (ovec3f_get_length(&accel_mean) - 9.82f < gravity_tolerance)
|
||||
{
|
||||
// Calculate a cross product between what the device
|
||||
// thinks is up and what gravity indicates is down.
|
||||
// The values are optimized of what we would get out
|
||||
// from the cross product.
|
||||
vec3f tilt = {{accel_mean.z, 0, -accel_mean.x}};
|
||||
|
||||
ovec3f_normalize_me(&tilt);
|
||||
ovec3f_normalize_me(&accel_mean);
|
||||
|
||||
vec3f up = {{0, 1.0f, 0}};
|
||||
float tilt_angle = ovec3f_get_angle(&up, &accel_mean);
|
||||
|
||||
if(tilt_angle > max_tilt_error){
|
||||
me->grav_error_angle = tilt_angle;
|
||||
me->grav_error_axis = tilt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preform gravity tilt correction
|
||||
if(me->grav_error_angle > min_tilt_error){
|
||||
float use_angle;
|
||||
// if less than 2000 iterations have passed, set the up axis to the correction value outright
|
||||
if(me->iterations < 2000){
|
||||
use_angle = -me->grav_error_angle;
|
||||
me->grav_error_angle = 0;
|
||||
}
|
||||
|
||||
// otherwise try to correct
|
||||
else {
|
||||
use_angle = -me->grav_gain * me->grav_error_angle * 0.005f * (5.0f * ang_vel_length + 1.0f);
|
||||
me->grav_error_angle += use_angle;
|
||||
}
|
||||
|
||||
// perform the correction
|
||||
quatf corr_quat, old_orient;
|
||||
oquatf_init_axis(&corr_quat, &me->grav_error_axis, use_angle);
|
||||
old_orient = me->orient;
|
||||
|
||||
oquatf_mult(&corr_quat, &old_orient, &me->orient);
|
||||
}
|
||||
}
|
||||
|
||||
// mitigate drift due to floating point
|
||||
// inprecision with quat multiplication.
|
||||
oquatf_normalize_me(&me->orient);
|
||||
}
|
44
extern/openhmd/src/fusion.h
vendored
Normal file
44
extern/openhmd/src/fusion.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Sensor Fusion */
|
||||
|
||||
#ifndef FUSION_H
|
||||
#define FUSION_H
|
||||
|
||||
#include "omath.h"
|
||||
|
||||
#define FF_USE_GRAVITY 1
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
|
||||
quatf orient; // orientation
|
||||
vec3f accel; // acceleration
|
||||
vec3f ang_vel; // angular velocity
|
||||
vec3f mag; // magnetometer
|
||||
vec3f raw_mag; // raw magnetometer values
|
||||
|
||||
int iterations;
|
||||
float time;
|
||||
|
||||
int flags;
|
||||
|
||||
// filter queues for magnetometer, accelerometers and angular velocity
|
||||
filter_queue mag_fq, accel_fq, ang_vel_fq;
|
||||
|
||||
// gravity correction
|
||||
int device_level_count;
|
||||
float grav_error_angle;
|
||||
vec3f grav_error_axis;
|
||||
float grav_gain; // amount of correction
|
||||
} fusion;
|
||||
|
||||
void ofusion_init(fusion* me);
|
||||
void ofusion_update(fusion* me, float dt, const vec3f* ang_vel, const vec3f* accel, const vec3f* mag_field);
|
||||
|
||||
#endif
|
39
extern/openhmd/src/log.h
vendored
Normal file
39
extern/openhmd/src/log.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Logging and Error Handling */
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
void* ohmd_allocfn(ohmd_context* ctx, const char* e_msg, size_t size);
|
||||
#define ohmd_alloc(_ctx, _size) ohmd_allocfn(_ctx, "could not allocate " #_size " bytes of RAM @ " __FILE__ ":" OHMD_STRINGIFY(__LINE__), _size)
|
||||
|
||||
#ifndef LOGLEVEL
|
||||
#define LOGLEVEL 2
|
||||
#endif
|
||||
|
||||
#define LOG(_level, _levelstr, ...) do{ if(_level >= LOGLEVEL){ printf("[%s] ", (_levelstr)); printf(__VA_ARGS__); puts(""); } } while(0)
|
||||
|
||||
#if LOGLEVEL == 0
|
||||
#define LOGD(...) LOG(0, "DD", __VA_ARGS__)
|
||||
#else
|
||||
#define LOGD(...)
|
||||
#endif
|
||||
|
||||
#define LOGV(...) LOG(1, "VV", __VA_ARGS__)
|
||||
#define LOGI(...) LOG(2, "II", __VA_ARGS__)
|
||||
#define LOGW(...) LOG(3, "WW", __VA_ARGS__)
|
||||
#define LOGE(...) LOG(4, "EE", __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define ohmd_set_error(_ctx, ...) { snprintf((_ctx)->error_msg, OHMD_STR_SIZE, __VA_ARGS__); LOGE(__VA_ARGS__); }
|
||||
|
||||
#endif
|
395
extern/openhmd/src/omath.c
vendored
Normal file
395
extern/openhmd/src/omath.c
vendored
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Math Code Implementation */
|
||||
|
||||
#include <string.h>
|
||||
#include "openhmdi.h"
|
||||
|
||||
// vector
|
||||
|
||||
float ovec3f_get_length(const vec3f* me)
|
||||
{
|
||||
return sqrtf(POW2(me->x) + POW2(me->y) + POW2(me->z));
|
||||
}
|
||||
|
||||
void ovec3f_normalize_me(vec3f* me)
|
||||
{
|
||||
if(me->x == 0 && me->y == 0 && me->z == 0)
|
||||
return;
|
||||
|
||||
float len = ovec3f_get_length(me);
|
||||
me->x /= len;
|
||||
me->y /= len;
|
||||
me->z /= len;
|
||||
}
|
||||
|
||||
void ovec3f_subtract(const vec3f* a, const vec3f* b, vec3f* out)
|
||||
{
|
||||
for(int i = 0; i < 3; i++)
|
||||
out->arr[i] = a->arr[i] - b->arr[i];
|
||||
}
|
||||
|
||||
float ovec3f_get_dot(const vec3f* me, const vec3f* vec)
|
||||
{
|
||||
return me->x * vec->x + me->y * vec->y + me->z * vec->z;
|
||||
}
|
||||
|
||||
float ovec3f_get_angle(const vec3f* me, const vec3f* vec)
|
||||
{
|
||||
float dot = ovec3f_get_dot(me, vec);
|
||||
float lengths = ovec3f_get_length(me) * ovec3f_get_length(vec);
|
||||
|
||||
if(lengths == 0)
|
||||
return 0;
|
||||
|
||||
return acosf(dot / lengths);
|
||||
}
|
||||
|
||||
|
||||
// quaternion
|
||||
|
||||
void oquatf_init_axis(quatf* me, const vec3f* vec, float angle)
|
||||
{
|
||||
vec3f norm = *vec;
|
||||
ovec3f_normalize_me(&norm);
|
||||
|
||||
me->x = norm.x * sinf(angle / 2.0f);
|
||||
me->y = norm.y * sinf(angle / 2.0f);
|
||||
me->z = norm.z * sinf(angle / 2.0f);
|
||||
me->w = cosf(angle / 2.0f);
|
||||
}
|
||||
|
||||
void oquatf_get_rotated(const quatf* me, const vec3f* vec, vec3f* out_vec)
|
||||
{
|
||||
quatf q = {{vec->x * me->w + vec->z * me->y - vec->y * me->z,
|
||||
vec->y * me->w + vec->x * me->z - vec->z * me->x,
|
||||
vec->z * me->w + vec->y * me->x - vec->x * me->y,
|
||||
vec->x * me->x + vec->y * me->y + vec->z * me->z}};
|
||||
|
||||
out_vec->x = me->w * q.x + me->x * q.w + me->y * q.z - me->z * q.y;
|
||||
out_vec->y = me->w * q.y + me->y * q.w + me->z * q.x - me->x * q.z;
|
||||
out_vec->z = me->w * q.z + me->z * q.w + me->x * q.y - me->y * q.x;
|
||||
}
|
||||
|
||||
void oquatf_mult(const quatf* me, const quatf* q, quatf* out_q)
|
||||
{
|
||||
out_q->x = me->w * q->x + me->x * q->w + me->y * q->z - me->z * q->y;
|
||||
out_q->y = me->w * q->y - me->x * q->z + me->y * q->w + me->z * q->x;
|
||||
out_q->z = me->w * q->z + me->x * q->y - me->y * q->x + me->z * q->w;
|
||||
out_q->w = me->w * q->w - me->x * q->x - me->y * q->y - me->z * q->z;
|
||||
}
|
||||
|
||||
void oquatf_mult_me(quatf* me, const quatf* q)
|
||||
{
|
||||
quatf tmp = *me;
|
||||
oquatf_mult(&tmp, q, me);
|
||||
}
|
||||
|
||||
void oquatf_normalize_me(quatf* me)
|
||||
{
|
||||
float len = oquatf_get_length(me);
|
||||
me->x /= len;
|
||||
me->y /= len;
|
||||
me->z /= len;
|
||||
me->w /= len;
|
||||
}
|
||||
|
||||
float oquatf_get_length(const quatf* me)
|
||||
{
|
||||
return sqrtf(me->x * me->x + me->y * me->y + me->z * me->z + me->w * me->w);
|
||||
}
|
||||
|
||||
float oquatf_get_dot(const quatf* me, const quatf* q)
|
||||
{
|
||||
return me->x * q->x + me->y * q->y + me->z * q->z + me->w * q->w;
|
||||
}
|
||||
|
||||
void oquatf_inverse(quatf* me)
|
||||
{
|
||||
float dot = oquatf_get_dot(me, me);
|
||||
|
||||
// conjugate
|
||||
for(int i = 0; i < 3; i++)
|
||||
me->arr[i] = -me->arr[i];
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
me->arr[i] /= dot;
|
||||
}
|
||||
|
||||
void oquatf_diff(const quatf* me, const quatf* q, quatf* out_q)
|
||||
{
|
||||
quatf inv = *me;
|
||||
oquatf_inverse(&inv);
|
||||
oquatf_mult(&inv, q, out_q);
|
||||
}
|
||||
|
||||
void oquatf_slerp (float fT, const quatf* rkP, const quatf* rkQ, bool shortestPath, quatf* out_q)
|
||||
{
|
||||
float fCos = oquatf_get_dot(rkP, rkQ);
|
||||
quatf rkT;
|
||||
|
||||
// Do we need to invert rotation?
|
||||
if (fCos < 0.0f && shortestPath)
|
||||
{
|
||||
fCos = -fCos;
|
||||
rkT = *rkQ;
|
||||
oquatf_inverse(&rkT);
|
||||
}
|
||||
else
|
||||
{
|
||||
rkT = *rkQ;
|
||||
}
|
||||
|
||||
if (fabsf(fCos) < 1 - 0.001f)
|
||||
{
|
||||
// Standard case (slerp)
|
||||
float fSin = sqrtf(1 - (fCos*fCos));
|
||||
float fAngle = atan2f(fSin, fCos);
|
||||
float fInvSin = 1.0f / fSin;
|
||||
float fCoeff0 = sin((1.0f - fT) * fAngle) * fInvSin;
|
||||
float fCoeff1 = sin(fT * fAngle) * fInvSin;
|
||||
|
||||
out_q->x = fCoeff0 * rkP->x + fCoeff1 * rkT.x;
|
||||
out_q->y = fCoeff0 * rkP->y + fCoeff1 * rkT.y;
|
||||
out_q->z = fCoeff0 * rkP->z + fCoeff1 * rkT.z;
|
||||
out_q->w = fCoeff0 * rkP->w + fCoeff1 * rkT.w;
|
||||
|
||||
//return fCoeff0 * rkP + fCoeff1 * rkT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are two situations:
|
||||
// 1. "rkP" and "rkQ" are very close (fCos ~= +1), so we can do a linear
|
||||
// interpolation safely.
|
||||
// 2. "rkP" and "rkQ" are almost inverse of each other (fCos ~= -1), there
|
||||
// are an infinite number of possibilities interpolation. but we haven't
|
||||
// have method to fix this case, so just use linear interpolation here.
|
||||
//Quaternion t = (1.0f - fT) * rkP + fT * rkT;
|
||||
|
||||
out_q->x = (1.0f - fT) * rkP->x + fT * rkT.x;
|
||||
out_q->y = (1.0f - fT) * rkP->y + fT * rkT.y;
|
||||
out_q->z = (1.0f - fT) * rkP->z + fT * rkT.z;
|
||||
out_q->w = (1.0f - fT) * rkP->w + fT * rkT.w;
|
||||
|
||||
oquatf_normalize_me(out_q);
|
||||
|
||||
// taking the complement requires renormalisation
|
||||
//t.normalise();
|
||||
//return t;
|
||||
}
|
||||
}
|
||||
|
||||
void oquatf_get_mat4x4(const quatf* me, const vec3f* point, float mat[4][4])
|
||||
{
|
||||
mat[0][0] = 1 - 2 * me->y * me->y - 2 * me->z * me->z;
|
||||
mat[0][1] = 2 * me->x * me->y - 2 * me->w * me->z;
|
||||
mat[0][2] = 2 * me->x * me->z + 2 * me->w * me->y;
|
||||
mat[0][3] = point->x;
|
||||
|
||||
mat[1][0] = 2 * me->x * me->y + 2 * me->w * me->z;
|
||||
mat[1][1] = 1 - 2 * me->x * me->x - 2 * me->z * me->z;
|
||||
mat[1][2] = 2 * me->y * me->z - 2 * me->w * me->x;
|
||||
mat[1][3] = point->y;
|
||||
|
||||
mat[2][0] = 2 * me->x * me->z - 2 * me->w * me->y;
|
||||
mat[2][1] = 2 * me->y * me->z + 2 * me->w * me->x;
|
||||
mat[2][2] = 1 - 2 * me->x * me->x - 2 * me->y * me->y;
|
||||
mat[2][3] = point->z;
|
||||
|
||||
mat[3][0] = 0;
|
||||
mat[3][1] = 0;
|
||||
mat[3][2] = 0;
|
||||
mat[3][3] = 1;
|
||||
}
|
||||
|
||||
|
||||
// matrix
|
||||
|
||||
void omat4x4f_init_ident(mat4x4f* me)
|
||||
{
|
||||
memset(me, 0, sizeof(*me));
|
||||
me->m[0][0] = 1.0f;
|
||||
me->m[1][1] = 1.0f;
|
||||
me->m[2][2] = 1.0f;
|
||||
me->m[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void omat4x4f_init_perspective(mat4x4f* me, float fovy_rad, float aspect, float znear, float zfar)
|
||||
{
|
||||
float sine, cotangent, delta, half_fov;
|
||||
|
||||
half_fov = fovy_rad / 2.0f;
|
||||
delta = zfar - znear;
|
||||
sine = sinf(half_fov);
|
||||
|
||||
if ((delta == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
|
||||
omat4x4f_init_ident(me);
|
||||
return;
|
||||
}
|
||||
|
||||
cotangent = cosf(half_fov) / sine;
|
||||
|
||||
me->m[0][0] = cotangent / aspect;
|
||||
me->m[0][1] = 0;
|
||||
me->m[0][2] = 0;
|
||||
me->m[0][3] = 0;
|
||||
|
||||
me->m[1][0] = 0;
|
||||
me->m[1][1] = cotangent;
|
||||
me->m[1][2] = 0;
|
||||
me->m[1][3] = 0;
|
||||
|
||||
me->m[2][0] = 0;
|
||||
me->m[2][1] = 0;
|
||||
me->m[2][2] = -(zfar + znear) / delta;
|
||||
me->m[2][3] = -2.0f * znear * zfar / delta;
|
||||
|
||||
me->m[3][0] = 0;
|
||||
me->m[3][1] = 0;
|
||||
me->m[3][2] = -1.0f;
|
||||
me->m[3][3] = 0;
|
||||
}
|
||||
|
||||
void omat4x4f_init_frustum(mat4x4f* me, float left, float right, float bottom, float top, float znear, float zfar)
|
||||
{
|
||||
omat4x4f_init_ident(me);
|
||||
|
||||
float delta_x = right - left;
|
||||
float delta_y = top - bottom;
|
||||
float delta_z = zfar - znear;
|
||||
if ((delta_x == 0.0f) || (delta_y == 0.0f) || (delta_z == 0.0f)) {
|
||||
/* can't divide by zero, so just give back identity */
|
||||
return;
|
||||
}
|
||||
|
||||
me->m[0][0] = 2.0f * znear / delta_x;
|
||||
me->m[0][1] = 0;
|
||||
me->m[0][2] = (right + left) / delta_x;
|
||||
me->m[0][3] = 0;
|
||||
|
||||
me->m[1][0] = 0;
|
||||
me->m[1][1] = 2.0f * znear / delta_y;
|
||||
me->m[1][2] = (top + bottom) / delta_y;
|
||||
me->m[1][3] = 0;
|
||||
|
||||
me->m[2][0] = 0;
|
||||
me->m[2][1] = 0;
|
||||
me->m[2][2] = -(zfar + znear) / delta_z;
|
||||
me->m[2][3] = -2.0f * zfar * znear / delta_z;
|
||||
|
||||
me->m[3][0] = 0;
|
||||
me->m[3][1] = 0;
|
||||
me->m[3][2] = -1.0f;
|
||||
me->m[3][3] = 0;
|
||||
}
|
||||
|
||||
void omat4x4f_init_look_at(mat4x4f* me, const quatf* rot, const vec3f* eye)
|
||||
{
|
||||
quatf q;
|
||||
vec3f p;
|
||||
|
||||
q.x = -rot->x;
|
||||
q.y = -rot->y;
|
||||
q.z = -rot->z;
|
||||
q.w = rot->w;
|
||||
|
||||
p.x = -eye->x;
|
||||
p.y = -eye->y;
|
||||
p.z = -eye->z;
|
||||
|
||||
me->m[0][0] = 1 - 2 * q.y * q.y - 2 * q.z * q.z;
|
||||
me->m[0][1] = 2 * q.x * q.y - 2 * q.w * q.z;
|
||||
me->m[0][2] = 2 * q.x * q.z + 2 * q.w * q.y;
|
||||
me->m[0][3] = p.x * me->m[0][0] + p.y * me->m[0][1] + p.z * me->m[0][2];
|
||||
|
||||
me->m[1][0] = 2 * q.x * q.y + 2 * q.w * q.z;
|
||||
me->m[1][1] = 1 - 2 * q.x * q.x - 2 * q.z * q.z;
|
||||
me->m[1][2] = 2 * q.y * q.z - 2 * q.w * q.x;
|
||||
me->m[1][3] = p.x * me->m[1][0] + p.y * me->m[1][1] + p.z * me->m[1][2];
|
||||
|
||||
me->m[2][0] = 2 * q.x * q.z - 2 * q.w * q.y;
|
||||
me->m[2][1] = 2 * q.y * q.z + 2 * q.w * q.x;
|
||||
me->m[2][2] = 1 - 2 * q.x * q.x - 2 * q.y * q.y;
|
||||
me->m[2][3] = p.x * me->m[2][0] + p.y * me->m[2][1] + p.z * me->m[2][2];
|
||||
|
||||
me->m[3][0] = 0;
|
||||
me->m[3][1] = 0;
|
||||
me->m[3][2] = 0;
|
||||
me->m[3][3] = 1;
|
||||
}
|
||||
|
||||
void omat4x4f_init_translate(mat4x4f* me, float x, float y, float z)
|
||||
{
|
||||
omat4x4f_init_ident(me);
|
||||
me->m[0][3] = x;
|
||||
me->m[1][3] = y;
|
||||
me->m[2][3] = z;
|
||||
}
|
||||
|
||||
void omat4x4f_transpose(const mat4x4f* m, mat4x4f* o)
|
||||
{
|
||||
o->m[0][0] = m->m[0][0];
|
||||
o->m[1][0] = m->m[0][1];
|
||||
o->m[2][0] = m->m[0][2];
|
||||
o->m[3][0] = m->m[0][3];
|
||||
|
||||
o->m[0][1] = m->m[1][0];
|
||||
o->m[1][1] = m->m[1][1];
|
||||
o->m[2][1] = m->m[1][2];
|
||||
o->m[3][1] = m->m[1][3];
|
||||
|
||||
o->m[0][2] = m->m[2][0];
|
||||
o->m[1][2] = m->m[2][1];
|
||||
o->m[2][2] = m->m[2][2];
|
||||
o->m[3][2] = m->m[2][3];
|
||||
|
||||
o->m[0][3] = m->m[3][0];
|
||||
o->m[1][3] = m->m[3][1];
|
||||
o->m[2][3] = m->m[3][2];
|
||||
o->m[3][3] = m->m[3][3];
|
||||
}
|
||||
|
||||
void omat4x4f_mult(const mat4x4f* l, const mat4x4f* r, mat4x4f *o)
|
||||
{
|
||||
for(int i = 0; i < 4; i++){
|
||||
float a0 = l->m[i][0], a1 = l->m[i][1], a2 = l->m[i][2], a3 = l->m[i][3];
|
||||
o->m[i][0] = a0 * r->m[0][0] + a1 * r->m[1][0] + a2 * r->m[2][0] + a3 * r->m[3][0];
|
||||
o->m[i][1] = a0 * r->m[0][1] + a1 * r->m[1][1] + a2 * r->m[2][1] + a3 * r->m[3][1];
|
||||
o->m[i][2] = a0 * r->m[0][2] + a1 * r->m[1][2] + a2 * r->m[2][2] + a3 * r->m[3][2];
|
||||
o->m[i][3] = a0 * r->m[0][3] + a1 * r->m[1][3] + a2 * r->m[2][3] + a3 * r->m[3][3];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// filter queue
|
||||
|
||||
void ofq_init(filter_queue* me, int size)
|
||||
{
|
||||
memset(me, 0, sizeof(filter_queue));
|
||||
me->size = size;
|
||||
}
|
||||
|
||||
void ofq_add(filter_queue* me, const vec3f* vec)
|
||||
{
|
||||
me->elems[me->at] = *vec;
|
||||
me->at = ((me->at + 1) % me->size);
|
||||
}
|
||||
|
||||
void ofq_get_mean(const filter_queue* me, vec3f* vec)
|
||||
{
|
||||
vec->x = vec->y = vec->z = 0;
|
||||
for(int i = 0; i < me->size; i++){
|
||||
vec->x += me->elems[i].x;
|
||||
vec->y += me->elems[i].y;
|
||||
vec->z += me->elems[i].z;
|
||||
}
|
||||
|
||||
vec->x /= (float)me->size;
|
||||
vec->y /= (float)me->size;
|
||||
vec->z /= (float)me->size;
|
||||
}
|
90
extern/openhmd/src/omath.h
vendored
Normal file
90
extern/openhmd/src/omath.h
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Math */
|
||||
|
||||
#ifndef OMATH_H
|
||||
#define OMATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define POW2(_x) ((_x) * (_x))
|
||||
#define RAD_TO_DEG(_r) ((_r) * 360.0f / (2.0f * (float)M_PI))
|
||||
#define DEG_TO_RAD(_d) ((_d) * (2.0f * (float)M_PI) / 360.0f)
|
||||
|
||||
|
||||
// vector
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
float x, y, z;
|
||||
};
|
||||
float arr[3];
|
||||
} vec3f;
|
||||
|
||||
void ovec3f_normalize_me(vec3f* me);
|
||||
float ovec3f_get_length(const vec3f* me);
|
||||
float ovec3f_get_angle(const vec3f* me, const vec3f* vec);
|
||||
float ovec3f_get_dot(const vec3f* me, const vec3f* vec);
|
||||
void ovec3f_subtract(const vec3f* a, const vec3f* b, vec3f* out);
|
||||
|
||||
|
||||
// quaternion
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
float x, y, z, w;
|
||||
};
|
||||
float arr[4];
|
||||
} quatf;
|
||||
|
||||
void oquatf_init_axis(quatf* me, const vec3f* vec, float angle);
|
||||
|
||||
void oquatf_get_rotated(const quatf* me, const vec3f* vec, vec3f* out_vec);
|
||||
void oquatf_mult_me(quatf* me, const quatf* q);
|
||||
void oquatf_mult(const quatf* me, const quatf* q, quatf* out_q);
|
||||
void oquatf_diff(const quatf* me, const quatf* q, quatf* out_q);
|
||||
void oquatf_normalize_me(quatf* me);
|
||||
float oquatf_get_length(const quatf* me);
|
||||
float oquatf_get_dot(const quatf* me, const quatf* q);
|
||||
void oquatf_inverse(quatf* me);
|
||||
|
||||
void oquatf_get_mat4x4(const quatf* me, const vec3f* point, float mat[4][4]);
|
||||
|
||||
// matrix
|
||||
|
||||
typedef union {
|
||||
float m[4][4];
|
||||
float arr[16];
|
||||
} mat4x4f;
|
||||
|
||||
void omat4x4f_init_ident(mat4x4f* me);
|
||||
void omat4x4f_init_perspective(mat4x4f* me, float fov_rad, float aspect, float znear, float zfar);
|
||||
void omat4x4f_init_frustum(mat4x4f* me, float left, float right, float bottom, float top, float znear, float zfar);
|
||||
void omat4x4f_init_look_at(mat4x4f* me, const quatf* ret, const vec3f* eye);
|
||||
void omat4x4f_init_translate(mat4x4f* me, float x, float y, float z);
|
||||
void omat4x4f_mult(const mat4x4f* left, const mat4x4f* right, mat4x4f* out_mat);
|
||||
void omat4x4f_transpose(const mat4x4f* me, mat4x4f* out_mat);
|
||||
|
||||
|
||||
// filter queue
|
||||
#define FILTER_QUEUE_MAX_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
int at, size;
|
||||
vec3f elems[FILTER_QUEUE_MAX_SIZE];
|
||||
} filter_queue;
|
||||
|
||||
void ofq_init(filter_queue* me, int size);
|
||||
void ofq_add(filter_queue* me, const vec3f* vec);
|
||||
void ofq_get_mean(const filter_queue* me, vec3f* vec);
|
||||
|
||||
#endif
|
572
extern/openhmd/src/openhmd.c
vendored
Normal file
572
extern/openhmd/src/openhmd.c
vendored
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Main Lib Implemenation */
|
||||
|
||||
#include "openhmdi.h"
|
||||
#include "shaders.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIGITAL_INPUT_EVENT_QUEUE_SIZE 1024
|
||||
|
||||
// Running automatic updates at 1000 Hz
|
||||
#define AUTOMATIC_UPDATE_SLEEP (1.0 / 1000.0)
|
||||
|
||||
ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void)
|
||||
{
|
||||
ohmd_context* ctx = calloc(1, sizeof(ohmd_context));
|
||||
if(!ctx){
|
||||
LOGE("could not allocate RAM for context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if DRIVER_OCULUS_RIFT
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_oculus_rift_drv(ctx);
|
||||
#endif
|
||||
|
||||
#if DRIVER_DEEPOON
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_deepoon_drv(ctx);
|
||||
#endif
|
||||
|
||||
#if DRIVER_PSVR
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_psvr_drv(ctx);
|
||||
#endif
|
||||
|
||||
#if DRIVER_HTC_VIVE
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_htc_vive_drv(ctx);
|
||||
#endif
|
||||
|
||||
#if DRIVER_EXTERNAL
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_external_drv(ctx);
|
||||
#endif
|
||||
|
||||
#if DRIVER_ANDROID
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_android_drv(ctx);
|
||||
#endif
|
||||
// add dummy driver last to make it the lowest priority
|
||||
ctx->drivers[ctx->num_drivers++] = ohmd_create_dummy_drv(ctx);
|
||||
|
||||
ctx->update_request_quit = false;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void OHMD_APIENTRY ohmd_ctx_destroy(ohmd_context* ctx)
|
||||
{
|
||||
ctx->update_request_quit = true;
|
||||
|
||||
for(int i = 0; i < ctx->num_active_devices; i++){
|
||||
ctx->active_devices[i]->close(ctx->active_devices[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < ctx->num_drivers; i++){
|
||||
ctx->drivers[i]->destroy(ctx->drivers[i]);
|
||||
}
|
||||
|
||||
if(ctx->update_thread){
|
||||
ohmd_destroy_thread(ctx->update_thread);
|
||||
ohmd_destroy_mutex(ctx->update_mutex);
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx)
|
||||
{
|
||||
for(int i = 0; i < ctx->num_active_devices; i++){
|
||||
ohmd_device* dev = ctx->active_devices[i];
|
||||
if(!dev->settings.automatic_update && dev->update)
|
||||
dev->update(dev);
|
||||
|
||||
ohmd_lock_mutex(ctx->update_mutex);
|
||||
dev->getf(dev, OHMD_POSITION_VECTOR, (float*)&dev->position);
|
||||
dev->getf(dev, OHMD_ROTATION_QUAT, (float*)&dev->rotation);
|
||||
ohmd_unlock_mutex(ctx->update_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
const char* OHMD_APIENTRY ohmd_ctx_get_error(ohmd_context* ctx)
|
||||
{
|
||||
return ctx->error_msg;
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx)
|
||||
{
|
||||
memset(&ctx->list, 0, sizeof(ohmd_device_list));
|
||||
for(int i = 0; i < ctx->num_drivers; i++){
|
||||
ctx->drivers[i]->get_device_list(ctx->drivers[i], &ctx->list);
|
||||
}
|
||||
|
||||
return ctx->list.num_devices;
|
||||
}
|
||||
|
||||
const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type)
|
||||
{
|
||||
switch(type){
|
||||
case OHMD_GLSL_DISTORTION_VERT_SRC:
|
||||
return distortion_vert;
|
||||
case OHMD_GLSL_DISTORTION_FRAG_SRC:
|
||||
return distortion_frag;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int index, ohmd_string_value type)
|
||||
{
|
||||
if(index >= ctx->list.num_devices)
|
||||
return NULL;
|
||||
|
||||
switch(type){
|
||||
case OHMD_VENDOR:
|
||||
return ctx->list.devices[index].vendor;
|
||||
case OHMD_PRODUCT:
|
||||
return ctx->list.devices[index].product;
|
||||
case OHMD_PATH:
|
||||
return ctx->list.devices[index].path;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int ohmd_update_thread(void* arg)
|
||||
{
|
||||
ohmd_context* ctx = (ohmd_context*)arg;
|
||||
|
||||
while(!ctx->update_request_quit)
|
||||
{
|
||||
ohmd_lock_mutex(ctx->update_mutex);
|
||||
|
||||
for(int i = 0; i < ctx->num_active_devices; i++){
|
||||
if(ctx->active_devices[i]->settings.automatic_update && ctx->active_devices[i]->update)
|
||||
ctx->active_devices[i]->update(ctx->active_devices[i]);
|
||||
}
|
||||
|
||||
ohmd_unlock_mutex(ctx->update_mutex);
|
||||
|
||||
ohmd_sleep(AUTOMATIC_UPDATE_SLEEP);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohmd_set_up_update_thread(ohmd_context* ctx)
|
||||
{
|
||||
if(!ctx->update_thread){
|
||||
ctx->update_mutex = ohmd_create_mutex(ctx);
|
||||
ctx->update_thread = ohmd_create_thread(ctx, ohmd_update_thread, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index, ohmd_device_settings* settings)
|
||||
{
|
||||
ohmd_lock_mutex(ctx->update_mutex);
|
||||
|
||||
if(index >= 0 && index < ctx->list.num_devices){
|
||||
|
||||
ohmd_device_desc* desc = &ctx->list.devices[index];
|
||||
ohmd_driver* driver = (ohmd_driver*)desc->driver_ptr;
|
||||
ohmd_device* device = driver->open_device(driver, desc);
|
||||
|
||||
if (device == NULL)
|
||||
return NULL;
|
||||
|
||||
device->rotation_correction.w = 1;
|
||||
|
||||
device->settings = *settings;
|
||||
|
||||
device->ctx = ctx;
|
||||
device->active_device_idx = ctx->num_active_devices;
|
||||
ctx->active_devices[ctx->num_active_devices++] = device;
|
||||
|
||||
if(device->properties.digital_button_count > 0)
|
||||
device->digital_input_event_queue = ohmdq_create(ctx, sizeof(ohmd_digital_input_event), DIGITAL_INPUT_EVENT_QUEUE_SIZE);
|
||||
|
||||
ohmd_unlock_mutex(ctx->update_mutex);
|
||||
|
||||
if(device->settings.automatic_update)
|
||||
ohmd_set_up_update_thread(ctx);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
ohmd_unlock_mutex(ctx->update_mutex);
|
||||
|
||||
ohmd_set_error(ctx, "no device with index: %d", index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ohmd_device* OHMD_APIENTRY ohmd_list_open_device(ohmd_context* ctx, int index)
|
||||
{
|
||||
ohmd_device_settings settings;
|
||||
|
||||
settings.automatic_update = true;
|
||||
|
||||
return ohmd_list_open_device_s(ctx, index, &settings);
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_close_device(ohmd_device* device)
|
||||
{
|
||||
ohmd_lock_mutex(device->ctx->update_mutex);
|
||||
|
||||
ohmd_context* ctx = device->ctx;
|
||||
int idx = device->active_device_idx;
|
||||
ohmdq* dinq = device->digital_input_event_queue;
|
||||
|
||||
memmove(ctx->active_devices + idx, ctx->active_devices + idx + 1,
|
||||
sizeof(ohmd_device*) * (ctx->num_active_devices - idx - 1));
|
||||
|
||||
device->close(device);
|
||||
|
||||
if(dinq)
|
||||
ohmdq_destroy(dinq);
|
||||
|
||||
ctx->num_active_devices--;
|
||||
|
||||
for(int i = idx; i < ctx->num_active_devices; i++)
|
||||
ctx->active_devices[i]->active_device_idx--;
|
||||
|
||||
ohmd_unlock_mutex(ctx->update_mutex);
|
||||
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
|
||||
static int ohmd_device_getf_unp(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
switch(type){
|
||||
case OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX: {
|
||||
vec3f point = {{0, 0, 0}};
|
||||
quatf rot = device->rotation;
|
||||
quatf tmp = device->rotation_correction;
|
||||
oquatf_mult_me(&tmp, &rot);
|
||||
rot = tmp;
|
||||
mat4x4f orient, world_shift, result;
|
||||
omat4x4f_init_look_at(&orient, &rot, &point);
|
||||
omat4x4f_init_translate(&world_shift, +(device->properties.ipd / 2.0f), 0, 0);
|
||||
omat4x4f_mult(&world_shift, &orient, &result);
|
||||
omat4x4f_transpose(&result, (mat4x4f*)out);
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX: {
|
||||
vec3f point = {{0, 0, 0}};
|
||||
quatf rot = device->rotation;
|
||||
oquatf_mult_me(&rot, &device->rotation_correction);
|
||||
mat4x4f orient, world_shift, result;
|
||||
omat4x4f_init_look_at(&orient, &rot, &point);
|
||||
omat4x4f_init_translate(&world_shift, -(device->properties.ipd / 2.0f), 0, 0);
|
||||
omat4x4f_mult(&world_shift, &orient, &result);
|
||||
omat4x4f_transpose(&result, (mat4x4f*)out);
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_LEFT_EYE_GL_PROJECTION_MATRIX:
|
||||
omat4x4f_transpose(&device->properties.proj_left, (mat4x4f*)out);
|
||||
return OHMD_S_OK;
|
||||
case OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX:
|
||||
omat4x4f_transpose(&device->properties.proj_right, (mat4x4f*)out);
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_SCREEN_HORIZONTAL_SIZE:
|
||||
*out = device->properties.hsize;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_SCREEN_VERTICAL_SIZE:
|
||||
*out = device->properties.vsize;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_LENS_HORIZONTAL_SEPARATION:
|
||||
*out = device->properties.lens_sep;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_LENS_VERTICAL_POSITION:
|
||||
*out = device->properties.lens_vpos;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_RIGHT_EYE_FOV:
|
||||
case OHMD_LEFT_EYE_FOV:
|
||||
*out = device->properties.fov;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_RIGHT_EYE_ASPECT_RATIO:
|
||||
case OHMD_LEFT_EYE_ASPECT_RATIO:
|
||||
*out = device->properties.ratio;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_EYE_IPD:
|
||||
*out = device->properties.ipd;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_PROJECTION_ZFAR:
|
||||
*out = device->properties.zfar;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_PROJECTION_ZNEAR:
|
||||
*out = device->properties.znear;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_ROTATION_QUAT:
|
||||
{
|
||||
*(quatf*)out = device->rotation;
|
||||
|
||||
oquatf_mult_me((quatf*)out, &device->rotation_correction);
|
||||
quatf tmp = device->rotation_correction;
|
||||
oquatf_mult_me(&tmp, (quatf*)out);
|
||||
*(quatf*)out = tmp;
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_POSITION_VECTOR:
|
||||
{
|
||||
*(vec3f*)out = device->position;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
out[i] += device->position_correction.arr[i];
|
||||
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_UNIVERSAL_DISTORTION_K: {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
out[i] = device->properties.universal_distortion_k[i];
|
||||
}
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_UNIVERSAL_ABERRATION_K: {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
out[i] = device->properties.universal_aberration_k[i];
|
||||
}
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
default:
|
||||
return device->getf(device, type, out);
|
||||
}
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_float_value type, float* out)
|
||||
{
|
||||
ohmd_lock_mutex(device->ctx->update_mutex);
|
||||
int ret = ohmd_device_getf_unp(device, type, out);
|
||||
ohmd_unlock_mutex(device->ctx->update_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ohmd_device_setf_unp(ohmd_device* device, ohmd_float_value type, const float* in)
|
||||
{
|
||||
switch(type){
|
||||
case OHMD_EYE_IPD:
|
||||
device->properties.ipd = *in;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_PROJECTION_ZFAR:
|
||||
device->properties.zfar = *in;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_PROJECTION_ZNEAR:
|
||||
device->properties.znear = *in;
|
||||
return OHMD_S_OK;
|
||||
case OHMD_ROTATION_QUAT:
|
||||
{
|
||||
// adjust rotation correction
|
||||
quatf q;
|
||||
int ret = device->getf(device, OHMD_ROTATION_QUAT, (float*)&q);
|
||||
|
||||
if(ret != 0){
|
||||
return ret;
|
||||
}
|
||||
|
||||
oquatf_diff(&q, (quatf*)in, &device->rotation_correction);
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_POSITION_VECTOR:
|
||||
{
|
||||
// adjust position correction
|
||||
vec3f v;
|
||||
int ret = device->getf(device, OHMD_POSITION_VECTOR, (float*)&v);
|
||||
|
||||
if(ret != 0){
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
device->position_correction.arr[i] = in[i] - v.arr[i];
|
||||
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
case OHMD_EXTERNAL_SENSOR_FUSION:
|
||||
{
|
||||
if(device->setf == NULL)
|
||||
return OHMD_S_UNSUPPORTED;
|
||||
|
||||
return device->setf(device, type, in);
|
||||
}
|
||||
default:
|
||||
return OHMD_S_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, const float* in)
|
||||
{
|
||||
ohmd_lock_mutex(device->ctx->update_mutex);
|
||||
int ret = ohmd_device_setf_unp(device, type, in);
|
||||
ohmd_unlock_mutex(device->ctx->update_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out)
|
||||
{
|
||||
ohmdq* dinq = device->digital_input_event_queue;
|
||||
|
||||
switch(type){
|
||||
case OHMD_SCREEN_HORIZONTAL_RESOLUTION:
|
||||
*out = device->properties.hres;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_SCREEN_VERTICAL_RESOLUTION:
|
||||
*out = device->properties.vres;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_BUTTON_EVENT_COUNT:
|
||||
*out = dinq ? (int)ohmdq_get_size(dinq) : 0;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_BUTTON_EVENT_OVERFLOW:
|
||||
*out = dinq ? (ohmdq_get_size(dinq) == ohmdq_get_max(dinq)) : 0;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_BUTTON_COUNT:
|
||||
*out = device->properties.digital_button_count;
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_BUTTON_POP_EVENT: {
|
||||
ohmd_digital_input_event event;
|
||||
|
||||
if(!ohmdq_pop(dinq, &event)){
|
||||
return OHMD_S_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
out[0] = event.idx;
|
||||
out[1] = event.state;
|
||||
|
||||
return OHMD_S_OK;
|
||||
}
|
||||
|
||||
default:
|
||||
return OHMD_S_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, const int* in)
|
||||
{
|
||||
switch(type){
|
||||
default:
|
||||
return OHMD_S_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ohmd_device_set_data_unp(ohmd_device* device, ohmd_data_value type, const void* in)
|
||||
{
|
||||
switch(type){
|
||||
case OHMD_DRIVER_DATA:
|
||||
device->set_data(device, OHMD_DRIVER_DATA, in);
|
||||
return OHMD_S_OK;
|
||||
|
||||
case OHMD_DRIVER_PROPERTIES:
|
||||
device->set_data(device, OHMD_DRIVER_PROPERTIES, in);
|
||||
return OHMD_S_OK;
|
||||
|
||||
default:
|
||||
return OHMD_S_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, const void* in)
|
||||
{
|
||||
ohmd_lock_mutex(device->ctx->update_mutex);
|
||||
int ret = ohmd_device_set_data_unp(device, type, in);
|
||||
ohmd_unlock_mutex(device->ctx->update_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ohmd_status OHMD_APIENTRY ohmd_device_settings_seti(ohmd_device_settings* settings, ohmd_int_settings key, const int* val)
|
||||
{
|
||||
switch(key){
|
||||
case OHMD_IDS_AUTOMATIC_UPDATE:
|
||||
settings->automatic_update = val[0] == 0 ? false : true;
|
||||
return OHMD_S_OK;
|
||||
|
||||
default:
|
||||
return OHMD_S_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
ohmd_device_settings* OHMD_APIENTRY ohmd_device_settings_create(ohmd_context* ctx)
|
||||
{
|
||||
return ohmd_alloc(ctx, sizeof(ohmd_device_settings));
|
||||
}
|
||||
|
||||
void OHMD_APIENTRY ohmd_device_settings_destroy(ohmd_device_settings* settings)
|
||||
{
|
||||
free(settings);
|
||||
}
|
||||
|
||||
void* ohmd_allocfn(ohmd_context* ctx, const char* e_msg, size_t size)
|
||||
{
|
||||
void* ret = calloc(1, size);
|
||||
if(!ret)
|
||||
ohmd_set_error(ctx, "%s", e_msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ohmd_set_default_device_properties(ohmd_device_properties* props)
|
||||
{
|
||||
props->ipd = 0.061f;
|
||||
props->znear = 0.1f;
|
||||
props->zfar = 1000.0f;
|
||||
ohmd_set_universal_distortion_k(props, 0, 0, 0, 1);
|
||||
ohmd_set_universal_aberration_k(props, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
void ohmd_calc_default_proj_matrices(ohmd_device_properties* props)
|
||||
{
|
||||
mat4x4f proj_base; // base projection matrix
|
||||
|
||||
// Calculate where the lens is on each screen,
|
||||
// and with the given value offset the projection matrix.
|
||||
float screen_center = props->hsize / 4.0f;
|
||||
float lens_shift = screen_center - props->lens_sep / 2.0f;
|
||||
// XXX: on CV1, props->hsize > props->lens_sep / 2.0,
|
||||
// I am not sure about the implications, but just taking the absolute
|
||||
// value of the offset seems to work.
|
||||
float proj_offset = fabs(4.0f * lens_shift / props->hsize);
|
||||
|
||||
// Setup the base projection matrix. Each eye mostly have the
|
||||
// same projection matrix with the exception of the offset.
|
||||
omat4x4f_init_perspective(&proj_base, props->fov, props->ratio, props->znear, props->zfar);
|
||||
|
||||
// Setup the two adjusted projection matricies. Each is setup to deal
|
||||
// with the fact that the lens is not in the center of the screen.
|
||||
// These matrices only change of the hardware changes, so static.
|
||||
mat4x4f translate;
|
||||
|
||||
omat4x4f_init_translate(&translate, proj_offset, 0, 0);
|
||||
omat4x4f_mult(&translate, &proj_base, &props->proj_left);
|
||||
|
||||
omat4x4f_init_translate(&translate, -proj_offset, 0, 0);
|
||||
omat4x4f_mult(&translate, &proj_base, &props->proj_right);
|
||||
}
|
||||
|
||||
void ohmd_set_universal_distortion_k(ohmd_device_properties* props, float a, float b, float c, float d)
|
||||
{
|
||||
props->universal_distortion_k[0] = a;
|
||||
props->universal_distortion_k[1] = b;
|
||||
props->universal_distortion_k[2] = c;
|
||||
props->universal_distortion_k[3] = d;
|
||||
}
|
||||
|
||||
void ohmd_set_universal_aberration_k(ohmd_device_properties* props, float r, float g, float b)
|
||||
{
|
||||
props->universal_aberration_k[0] = r;
|
||||
props->universal_aberration_k[1] = g;
|
||||
props->universal_aberration_k[2] = b;
|
||||
}
|
152
extern/openhmd/src/openhmdi.h
vendored
Normal file
152
extern/openhmd/src/openhmdi.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Internal interface */
|
||||
|
||||
#ifndef OPENHMDI_H
|
||||
#define OPENHMDI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "openhmd.h"
|
||||
#include "omath.h"
|
||||
#include "platform.h"
|
||||
#include "queue.h"
|
||||
|
||||
#define OHMD_MAX_DEVICES 16
|
||||
|
||||
#define OHMD_MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
#define OHMD_MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
|
||||
|
||||
#define OHMD_STRINGIFY(_what) #_what
|
||||
|
||||
typedef struct ohmd_driver ohmd_driver;
|
||||
|
||||
typedef struct {
|
||||
char driver[OHMD_STR_SIZE];
|
||||
char vendor[OHMD_STR_SIZE];
|
||||
char product[OHMD_STR_SIZE];
|
||||
char path[OHMD_STR_SIZE];
|
||||
int revision;
|
||||
ohmd_driver* driver_ptr;
|
||||
} ohmd_device_desc;
|
||||
|
||||
typedef struct {
|
||||
int num_devices;
|
||||
ohmd_device_desc devices[OHMD_MAX_DEVICES];
|
||||
} ohmd_device_list;
|
||||
|
||||
typedef struct {
|
||||
int idx;
|
||||
ohmd_button_state state;
|
||||
} ohmd_digital_input_event;
|
||||
|
||||
struct ohmd_driver {
|
||||
void (*get_device_list)(ohmd_driver* driver, ohmd_device_list* list);
|
||||
ohmd_device* (*open_device)(ohmd_driver* driver, ohmd_device_desc* desc);
|
||||
void (*destroy)(ohmd_driver* driver);
|
||||
ohmd_context* ctx;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int hres;
|
||||
int vres;
|
||||
int digital_button_count;
|
||||
|
||||
float hsize;
|
||||
float vsize;
|
||||
|
||||
float lens_sep;
|
||||
float lens_vpos;
|
||||
|
||||
float fov;
|
||||
float ratio;
|
||||
|
||||
float ipd;
|
||||
float zfar;
|
||||
float znear;
|
||||
|
||||
int accel_only; //bool-like for setting acceleration only fallback (android driver)
|
||||
|
||||
mat4x4f proj_left; // adjusted projection matrix for left screen
|
||||
mat4x4f proj_right; // adjusted projection matrix for right screen
|
||||
float universal_distortion_k[4]; //PanoTools lens distiorion model [a,b,c,d]
|
||||
float universal_aberration_k[3]; //post-warp per channel scaling [r,g,b]
|
||||
} ohmd_device_properties;
|
||||
|
||||
struct ohmd_device_settings
|
||||
{
|
||||
bool automatic_update;
|
||||
};
|
||||
|
||||
struct ohmd_device {
|
||||
ohmd_device_properties properties;
|
||||
|
||||
quatf rotation_correction;
|
||||
vec3f position_correction;
|
||||
|
||||
int (*getf)(ohmd_device* device, ohmd_float_value type, float* out);
|
||||
int (*setf)(ohmd_device* device, ohmd_float_value type, const float* in);
|
||||
int (*seti)(ohmd_device* device, ohmd_int_value type, const int* in);
|
||||
int (*set_data)(ohmd_device* device, ohmd_data_value type, const void* in);
|
||||
|
||||
void (*update)(ohmd_device* device);
|
||||
void (*close)(ohmd_device* device);
|
||||
|
||||
ohmd_context* ctx;
|
||||
|
||||
ohmd_device_settings settings;
|
||||
|
||||
int active_device_idx; // index into ohmd_device->active_devices[]
|
||||
|
||||
quatf rotation;
|
||||
vec3f position;
|
||||
|
||||
ohmdq* digital_input_event_queue;
|
||||
};
|
||||
|
||||
|
||||
struct ohmd_context {
|
||||
ohmd_driver* drivers[16];
|
||||
int num_drivers;
|
||||
|
||||
ohmd_device_list list;
|
||||
|
||||
ohmd_device* active_devices[256];
|
||||
int num_active_devices;
|
||||
|
||||
ohmd_thread* update_thread;
|
||||
ohmd_mutex* update_mutex;
|
||||
|
||||
bool update_request_quit;
|
||||
|
||||
char error_msg[OHMD_STR_SIZE];
|
||||
};
|
||||
|
||||
// helper functions
|
||||
void ohmd_set_default_device_properties(ohmd_device_properties* props);
|
||||
void ohmd_calc_default_proj_matrices(ohmd_device_properties* props);
|
||||
void ohmd_set_universal_distortion_k(ohmd_device_properties* props, float a, float b, float c, float d);
|
||||
void ohmd_set_universal_aberration_k(ohmd_device_properties* props, float r, float g, float b);
|
||||
|
||||
// drivers
|
||||
ohmd_driver* ohmd_create_dummy_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_oculus_rift_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_deepoon_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_psvr_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_htc_vive_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_external_drv(ohmd_context* ctx);
|
||||
ohmd_driver* ohmd_create_android_drv(ohmd_context* ctx);
|
||||
|
||||
#include "log.h"
|
||||
#include "omath.h"
|
||||
#include "fusion.h"
|
||||
|
||||
#endif
|
132
extern/openhmd/src/platform-posix.c
vendored
Normal file
132
extern/openhmd/src/platform-posix.c
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Platform Specific Functions, Unix/Posix Implementation */
|
||||
|
||||
#if defined(__unix__) || defined(__unix) || defined(__APPLE__) || defined(__MACH__)
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#define CLOCK_MONOTONIC (clockid_t)4
|
||||
#endif
|
||||
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "openhmdi.h"
|
||||
|
||||
// Use clock_gettime if the system implements posix realtime timers
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
double ohmd_get_tick()
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (double)now.tv_sec * 1.0 + (double)now.tv_usec / 1000000.0;
|
||||
}
|
||||
#else
|
||||
double ohmd_get_tick()
|
||||
{
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return (double)now.tv_sec * 1.0 + (double)now.tv_nsec / 1000000000.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ohmd_sleep(double seconds)
|
||||
{
|
||||
struct timespec sleepfor;
|
||||
|
||||
sleepfor.tv_sec = (time_t)seconds;
|
||||
sleepfor.tv_nsec = (long)((seconds - sleepfor.tv_sec) * 1000000000.0);
|
||||
|
||||
nanosleep(&sleepfor, NULL);
|
||||
}
|
||||
|
||||
// threads
|
||||
struct ohmd_thread
|
||||
{
|
||||
pthread_t thread;
|
||||
unsigned int (*routine)(void* arg);
|
||||
void* arg;
|
||||
};
|
||||
|
||||
static void* pthread_wrapper(void* arg)
|
||||
{
|
||||
ohmd_thread* my_thread = (ohmd_thread*)arg;
|
||||
my_thread->routine(my_thread->arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg)
|
||||
{
|
||||
ohmd_thread* thread = ohmd_alloc(ctx, sizeof(ohmd_thread));
|
||||
if(thread == NULL)
|
||||
return NULL;
|
||||
|
||||
thread->arg = arg;
|
||||
thread->routine = routine;
|
||||
|
||||
int ret = pthread_create(&thread->thread, NULL, pthread_wrapper, thread);
|
||||
|
||||
if(ret != 0){
|
||||
free(thread);
|
||||
thread = NULL;
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx)
|
||||
{
|
||||
pthread_mutex_t* mutex = ohmd_alloc(ctx, sizeof(pthread_mutex_t));
|
||||
if(mutex == NULL)
|
||||
return NULL;
|
||||
|
||||
int ret = pthread_mutex_init(mutex, NULL);
|
||||
|
||||
if(ret != 0){
|
||||
free(mutex);
|
||||
mutex = NULL;
|
||||
}
|
||||
|
||||
return (ohmd_mutex*)mutex;
|
||||
}
|
||||
|
||||
void ohmd_destroy_thread(ohmd_thread* thread)
|
||||
{
|
||||
pthread_join(thread->thread, NULL);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
void ohmd_destroy_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
pthread_mutex_destroy((pthread_mutex_t*)mutex);
|
||||
free(mutex);
|
||||
}
|
||||
|
||||
void ohmd_lock_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
if(mutex)
|
||||
pthread_mutex_lock((pthread_mutex_t*)mutex);
|
||||
}
|
||||
|
||||
void ohmd_unlock_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
if(mutex)
|
||||
pthread_mutex_unlock((pthread_mutex_t*)mutex);
|
||||
}
|
||||
|
||||
/// Handling ovr service
|
||||
void ohmd_toggle_ovr_service(int state) //State is 0 for Disable, 1 for Enable
|
||||
{
|
||||
//Empty implementation
|
||||
}
|
||||
#endif
|
144
extern/openhmd/src/platform-win32.c
vendored
Normal file
144
extern/openhmd/src/platform-win32.c
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Platform Specific Functions, Win32 Implementation */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_EXTRA_LEAN
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "openhmdi.h"
|
||||
|
||||
double ohmd_get_tick()
|
||||
{
|
||||
double high, low;
|
||||
FILETIME filetime;
|
||||
|
||||
GetSystemTimeAsFileTime(&filetime);
|
||||
|
||||
high = filetime.dwHighDateTime;
|
||||
low = filetime.dwLowDateTime;
|
||||
|
||||
return (high * 4294967296.0 + low) / 10000000;
|
||||
}
|
||||
|
||||
// TODO higher resolution
|
||||
void ohmd_sleep(double seconds)
|
||||
{
|
||||
Sleep((DWORD)(seconds * 1000));
|
||||
}
|
||||
|
||||
// threads
|
||||
|
||||
struct ohmd_thread {
|
||||
HANDLE handle;
|
||||
void* arg;
|
||||
unsigned int (*routine)(void* arg);
|
||||
};
|
||||
|
||||
struct ohmd_mutex {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
DWORD __stdcall ohmd_thread_wrapper(void* t)
|
||||
{
|
||||
ohmd_thread* thread = (ohmd_thread*)t;
|
||||
return thread->routine(thread->arg);
|
||||
}
|
||||
|
||||
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg)
|
||||
{
|
||||
ohmd_thread* thread = ohmd_alloc(ctx, sizeof(ohmd_thread));
|
||||
if(!thread)
|
||||
return NULL;
|
||||
|
||||
thread->routine = routine;
|
||||
thread->arg = arg;
|
||||
|
||||
thread->handle = CreateThread(NULL, 0, ohmd_thread_wrapper, thread, 0, NULL);
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
void ohmd_destroy_thread(ohmd_thread* thread)
|
||||
{
|
||||
ohmd_sleep(3);
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx)
|
||||
{
|
||||
ohmd_mutex* mutex = ohmd_alloc(ctx, sizeof(ohmd_mutex));
|
||||
if(!mutex)
|
||||
return NULL;
|
||||
|
||||
mutex->handle = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void ohmd_destroy_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
CloseHandle(mutex->handle);
|
||||
free(mutex);
|
||||
}
|
||||
|
||||
void ohmd_lock_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
if(mutex)
|
||||
WaitForSingleObject(mutex->handle, INFINITE);
|
||||
}
|
||||
|
||||
void ohmd_unlock_mutex(ohmd_mutex* mutex)
|
||||
{
|
||||
if(mutex)
|
||||
ReleaseMutex(mutex->handle);
|
||||
}
|
||||
|
||||
/// Handling ovr service
|
||||
static int _enable_ovr_service = 0;
|
||||
|
||||
void ohmd_toggle_ovr_service(int state) //State is 0 for Disable, 1 for Enable
|
||||
{
|
||||
SC_HANDLE serviceDbHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
||||
SC_HANDLE serviceHandle = OpenService(serviceDbHandle, "OVRService", SC_MANAGER_ALL_ACCESS);
|
||||
|
||||
SERVICE_STATUS_PROCESS status;
|
||||
DWORD bytesNeeded;
|
||||
QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO,(LPBYTE) &status,sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded);
|
||||
|
||||
if (state == 0 || status.dwCurrentState == SERVICE_RUNNING)
|
||||
{
|
||||
// Stop it
|
||||
BOOL b = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &status);
|
||||
if (b)
|
||||
{
|
||||
printf("OVRService stopped\n");
|
||||
_enable_ovr_service = 1;
|
||||
}
|
||||
else
|
||||
printf("Error: OVRService failed to stop, please try running with Administrator rights\n");
|
||||
}
|
||||
else if (state == 1 && _enable_ovr_service)
|
||||
{
|
||||
// Start it
|
||||
BOOL b = StartService(serviceHandle, NULL, NULL);
|
||||
if (b)
|
||||
printf("OVRService started\n");
|
||||
else
|
||||
printf("Error: OVRService failed to start, please try running with Administrator rights\n");
|
||||
}
|
||||
CloseServiceHandle(serviceHandle);
|
||||
CloseServiceHandle(serviceDbHandle);
|
||||
}
|
||||
#endif
|
32
extern/openhmd/src/platform.h
vendored
Normal file
32
extern/openhmd/src/platform.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2013 Fredrik Hultin.
|
||||
* Copyright (C) 2013 Jakob Bornecrantz.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Internal Interface for Platform Specific Functions */
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "openhmd.h"
|
||||
|
||||
double ohmd_get_tick();
|
||||
void ohmd_sleep(double seconds);
|
||||
void ohmd_toggle_ovr_service(int state);
|
||||
|
||||
typedef struct ohmd_thread ohmd_thread;
|
||||
typedef struct ohmd_mutex ohmd_mutex;
|
||||
|
||||
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx);
|
||||
void ohmd_destroy_mutex(ohmd_mutex* mutex);
|
||||
|
||||
void ohmd_lock_mutex(ohmd_mutex* mutex);
|
||||
void ohmd_unlock_mutex(ohmd_mutex* mutex);
|
||||
|
||||
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg);
|
||||
void ohmd_destroy_thread(ohmd_thread* thread);
|
||||
|
||||
|
||||
#endif
|
97
extern/openhmd/src/queue.c
vendored
Normal file
97
extern/openhmd/src/queue.c
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2016 Fredrik Hultin.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Naive Thread Safe Circular Queue Implementation */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "openhmdi.h"
|
||||
|
||||
struct ohmdq {
|
||||
unsigned read_pos;
|
||||
unsigned write_pos;
|
||||
unsigned size;
|
||||
unsigned max;
|
||||
unsigned elem_size;
|
||||
char* elems;
|
||||
ohmd_mutex* mutex;
|
||||
};
|
||||
|
||||
ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max)
|
||||
{
|
||||
ohmdq* me = ohmd_alloc(ctx, sizeof(ohmdq));
|
||||
|
||||
me->elems = ohmd_alloc(ctx, elem_size * max);
|
||||
me->max = max;
|
||||
me->elem_size = elem_size;
|
||||
me->read_pos = 0;
|
||||
me->write_pos = 0;
|
||||
me->size = 0;
|
||||
me->mutex = ohmd_create_mutex(ctx);
|
||||
|
||||
return me;
|
||||
}
|
||||
|
||||
bool ohmdq_push(ohmdq* me, const void* elem)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
ohmd_lock_mutex(me->mutex);
|
||||
|
||||
if(me->size < me->max){
|
||||
memcpy(me->elems + me->write_pos, elem, me->elem_size);
|
||||
me->write_pos = (me->write_pos + me->elem_size) % (me->max * me->elem_size);
|
||||
me->size++;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ohmd_unlock_mutex(me->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ohmdq_pop(ohmdq* me, void* out_elem)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
ohmd_lock_mutex(me->mutex);
|
||||
|
||||
if(me->size > 0){
|
||||
memcpy(out_elem, me->elems + me->read_pos, me->elem_size);
|
||||
me->read_pos = (me->read_pos + me->elem_size) % (me->max * me->elem_size);
|
||||
me->size--;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ohmd_unlock_mutex(me->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned ohmdq_get_size(ohmdq* me)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
ohmd_lock_mutex(me->mutex);
|
||||
ret = me->size;
|
||||
ohmd_unlock_mutex(me->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned ohmdq_get_max(ohmdq* me)
|
||||
{
|
||||
return me->max;
|
||||
}
|
||||
|
||||
void ohmdq_destroy(ohmdq* me)
|
||||
{
|
||||
free(me->elems);
|
||||
ohmd_destroy_mutex(me->mutex);
|
||||
free(me);
|
||||
}
|
25
extern/openhmd/src/queue.h
vendored
Normal file
25
extern/openhmd/src/queue.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* OpenHMD - Free and Open Source API and drivers for immersive technology.
|
||||
* Copyright (C) 2016 Fredrik Hultin.
|
||||
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
|
||||
*/
|
||||
|
||||
/* Naive Thread Safe Circular Queue */
|
||||
|
||||
#ifndef OHMDQUEUE_H
|
||||
#define OHMDQUEUE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct ohmdq ohmdq;
|
||||
typedef struct ohmd_context ohmd_context;
|
||||
|
||||
ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max);
|
||||
void ohmdq_destroy(ohmdq* me);
|
||||
|
||||
bool ohmdq_push(ohmdq* me, const void* elem);
|
||||
bool ohmdq_pop(ohmdq* me, void* out_elem);
|
||||
unsigned ohmdq_get_size(ohmdq* me);
|
||||
unsigned ohmdq_get_max(ohmdq* me);
|
||||
|
||||
#endif
|
55
extern/openhmd/src/shaders.c
vendored
Normal file
55
extern/openhmd/src/shaders.c
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
const char * distortion_vert =
|
||||
"#version 120\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
"gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
|
||||
"}";
|
||||
|
||||
const char * distortion_frag =
|
||||
"#version 120\n"
|
||||
"\n"
|
||||
"//per eye texture to warp for lens distortion\n"
|
||||
"uniform sampler2D warpTexture;\n"
|
||||
"\n"
|
||||
"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
|
||||
"uniform vec2 LensCenter;\n"
|
||||
"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
|
||||
"uniform vec2 ViewportScale;\n"
|
||||
"//Distortion overall scale in m (usually ~eye_w/2)\n"
|
||||
"uniform float WarpScale;\n"
|
||||
"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
|
||||
"uniform vec4 HmdWarpParam;\n"
|
||||
"\n"
|
||||
"//chromatic distortion post scaling\n"
|
||||
"uniform vec3 aberr;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
|
||||
"vec2 output_loc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);\n"
|
||||
"//Compute fragment location in lens-centered co-ordinates at world scale\n"
|
||||
"vec2 r = output_loc * ViewportScale - LensCenter;\n"
|
||||
"//scale for distortion model\n"
|
||||
"//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
|
||||
"r /= WarpScale;\n"
|
||||
"\n"
|
||||
"//|r|**2\n"
|
||||
"float r_mag = length(r);\n"
|
||||
"//offset for which fragment is sourced\n"
|
||||
"vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
|
||||
"HmdWarpParam.y * r_mag * r_mag +\n"
|
||||
"HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
|
||||
"//back to world scale\n"
|
||||
"r_displaced *= WarpScale;\n"
|
||||
"//back to viewport co-ord\n"
|
||||
"vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
|
||||
"vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
|
||||
"vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
|
||||
"\n"
|
||||
"float red = texture2D(warpTexture, tc_r).r;\n"
|
||||
"float green = texture2D(warpTexture, tc_g).g;\n"
|
||||
"float blue = texture2D(warpTexture, tc_b).b;\n"
|
||||
"//Black edges off the texture\n"
|
||||
"gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
|
||||
"}";
|
6
extern/openhmd/src/shaders.h
vendored
Normal file
6
extern/openhmd/src/shaders.h
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef SHADERS_H
|
||||
#define SHADERS_H
|
||||
|
||||
const char * distortion_vert;
|
||||
const char * distortion_frag;
|
||||
#endif /* SHADERS_H */
|
38
extern/udew/CMakeLists.txt
vendored
Normal file
38
extern/udew/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2016, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Contributor(s): Sergey Sharybin.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
include
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
set(SRC
|
||||
include/udew.h
|
||||
src/udew.c
|
||||
)
|
||||
|
||||
blender_add_lib(extern_udew "${SRC}" "${INC}" "${INC_SYS}")
|
174
extern/udew/LICENSE
vendored
Normal file
174
extern/udew/LICENSE
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
|
||||
Modified Apache 2.0 License
|
||||
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor
|
||||
and its affiliates, except as required to comply with Section 4(c) of
|
||||
the License and to reproduce the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
14
extern/udew/README
vendored
Normal file
14
extern/udew/README
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
The udev Extension Wrangler Library (UDEW) is a cross-platform open-source
|
||||
C/C++ extension loading library. UDEW provides efficient run-time mechanisms
|
||||
for determining which udev functions and extensions extensions are supported
|
||||
on the target platform.
|
||||
|
||||
LICENSE
|
||||
|
||||
UDEW library is released under the Apache 2.0 license.
|
||||
|
||||
LIMITATIONS
|
||||
|
||||
- udev_device_get_parent_with_subsystem_devtype() need to be merged to a single
|
||||
line in the geader before generating the wrangler with stubs support
|
||||
- udev_set_log_fn() is not included into the stubs at all.
|
205
extern/udew/auto/libudev.h
vendored
Normal file
205
extern/udew/auto/libudev.h
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef _LIBUDEV_H_
|
||||
#define _LIBUDEV_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* udev - library context
|
||||
*
|
||||
* reads the udev config and system environment
|
||||
* allows custom logging
|
||||
*/
|
||||
struct udev;
|
||||
struct udev *udev_ref(struct udev *udev);
|
||||
struct udev *udev_unref(struct udev *udev);
|
||||
struct udev *udev_new(void);
|
||||
void udev_set_log_fn(struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority, const char *file, int line, const char *fn,
|
||||
const char *format, va_list args)) __attribute__ ((deprecated));
|
||||
int udev_get_log_priority(struct udev *udev) __attribute__ ((deprecated));
|
||||
void udev_set_log_priority(struct udev *udev, int priority) __attribute__ ((deprecated));
|
||||
void *udev_get_userdata(struct udev *udev);
|
||||
void udev_set_userdata(struct udev *udev, void *userdata);
|
||||
|
||||
/*
|
||||
* udev_list
|
||||
*
|
||||
* access to libudev generated lists
|
||||
*/
|
||||
struct udev_list_entry;
|
||||
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
|
||||
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
|
||||
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
|
||||
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
|
||||
/**
|
||||
* udev_list_entry_foreach:
|
||||
* @list_entry: entry to store the current position
|
||||
* @first_entry: first entry to start with
|
||||
*
|
||||
* Helper to iterate over all entries of a list.
|
||||
*/
|
||||
#define udev_list_entry_foreach(list_entry, first_entry) \
|
||||
for (list_entry = first_entry; \
|
||||
list_entry != NULL; \
|
||||
list_entry = udev_list_entry_get_next(list_entry))
|
||||
|
||||
/*
|
||||
* udev_device
|
||||
*
|
||||
* access to sysfs/kernel devices
|
||||
*/
|
||||
struct udev_device;
|
||||
struct udev_device *udev_device_ref(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_unref(struct udev_device *udev_device);
|
||||
struct udev *udev_device_get_udev(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
|
||||
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
|
||||
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
|
||||
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
|
||||
struct udev_device *udev_device_new_from_environment(struct udev *udev);
|
||||
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
|
||||
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||
/* retrieve device properties */
|
||||
const char *udev_device_get_devpath(struct udev_device *udev_device);
|
||||
const char *udev_device_get_subsystem(struct udev_device *udev_device);
|
||||
const char *udev_device_get_devtype(struct udev_device *udev_device);
|
||||
const char *udev_device_get_syspath(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysname(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysnum(struct udev_device *udev_device);
|
||||
const char *udev_device_get_devnode(struct udev_device *udev_device);
|
||||
int udev_device_get_is_initialized(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
|
||||
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
|
||||
const char *udev_device_get_driver(struct udev_device *udev_device);
|
||||
dev_t udev_device_get_devnum(struct udev_device *udev_device);
|
||||
const char *udev_device_get_action(struct udev_device *udev_device);
|
||||
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
|
||||
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
|
||||
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
|
||||
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
|
||||
|
||||
/*
|
||||
* udev_monitor
|
||||
*
|
||||
* access to kernel uevents and udev events
|
||||
*/
|
||||
struct udev_monitor;
|
||||
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
|
||||
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
|
||||
/* kernel and udev generated events over netlink */
|
||||
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
|
||||
/* bind socket */
|
||||
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
|
||||
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
|
||||
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
|
||||
/* in-kernel socket filters to select messages that get delivered to a listener */
|
||||
int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
|
||||
const char *subsystem, const char *devtype);
|
||||
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
|
||||
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
|
||||
|
||||
/*
|
||||
* udev_enumerate
|
||||
*
|
||||
* search sysfs for specific devices and provide a sorted list
|
||||
*/
|
||||
struct udev_enumerate;
|
||||
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
|
||||
/* device properties filter */
|
||||
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
|
||||
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
|
||||
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
|
||||
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
|
||||
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
|
||||
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
|
||||
/* run enumeration with active filters */
|
||||
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
|
||||
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
|
||||
/* return device list */
|
||||
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
|
||||
|
||||
/*
|
||||
* udev_queue
|
||||
*
|
||||
* access to the currently running udev events
|
||||
*/
|
||||
struct udev_queue;
|
||||
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
|
||||
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_new(struct udev *udev);
|
||||
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated));
|
||||
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated));
|
||||
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__ ((deprecated));
|
||||
int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
|
||||
unsigned long long int start, unsigned long long int end) __attribute__ ((deprecated));
|
||||
int udev_queue_get_fd(struct udev_queue *udev_queue);
|
||||
int udev_queue_flush(struct udev_queue *udev_queue);
|
||||
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__ ((deprecated));
|
||||
|
||||
/*
|
||||
* udev_hwdb
|
||||
*
|
||||
* access to the static hardware properties database
|
||||
*/
|
||||
struct udev_hwdb;
|
||||
struct udev_hwdb *udev_hwdb_new(struct udev *udev);
|
||||
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
|
||||
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
|
||||
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
|
||||
|
||||
/*
|
||||
* udev_util
|
||||
*
|
||||
* udev specific utilities
|
||||
*/
|
||||
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
245
extern/udew/auto/udew_gen.sh
vendored
Executable file
245
extern/udew/auto/udew_gen.sh
vendored
Executable file
@@ -0,0 +1,245 @@
|
||||
#!/bin/bash
|
||||
|
||||
#HEADER="/usr/include/libudev.h"
|
||||
HEADER="libudev.h"
|
||||
SCRIPT=`realpath -s $0`
|
||||
DIR=`dirname $SCRIPT`
|
||||
DIR=`dirname $DIR`
|
||||
H="$DIR/include/udew.h"
|
||||
C=$DIR/src/udew.c
|
||||
STUBS=true
|
||||
|
||||
mkdir -p $DIR/include
|
||||
mkdir -p $DIR/src
|
||||
|
||||
rm -rf $DIR/include/udew.h
|
||||
rm -rf $DIR/src/udew.c
|
||||
|
||||
echo "Generating udew headers..."
|
||||
|
||||
append() {
|
||||
f=`echo "$1" | sed ':a;N;$!ba;s/\n/\\\\n/g'`
|
||||
line_num=`grep -n '#ifdef __cplusplus' $H | cut -d : -f 1 | tail -n 1`
|
||||
gawk -i inplace "NR==$line_num {\$0=\"$f\n\n#ifdef __cplusplus\"} 1" $H
|
||||
}
|
||||
|
||||
cat $HEADER \
|
||||
| sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(/typedef \1t\4(/i' \
|
||||
> $H
|
||||
|
||||
if $STUBS; then
|
||||
fp="_";
|
||||
fi
|
||||
|
||||
f=`grep -E 'typedef ((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)t([a-z0-9_]+)\(' $H \
|
||||
| sed -r "s/((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)t([a-z0-9_]+)\(.*/extern t\4 *$fp\4;/i"`
|
||||
append "$f"
|
||||
|
||||
append "enum {\n\
|
||||
UDEW_SUCCESS = 0,\n\
|
||||
UDEW_ERROR_OPEN_FAILED = -1,\n\
|
||||
UDEW_ERROR_ATEXIT_FAILED = -2,\n\
|
||||
};\n\
|
||||
\n\
|
||||
int udewInit(void);"
|
||||
|
||||
if $STUBS; then
|
||||
decl=`cat $HEADER \
|
||||
| grep -E '^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(.*\);'`
|
||||
append "$decl"
|
||||
fi
|
||||
|
||||
sed -i 's/_LIBUDEV_H_/__UDEW_H__/g' $H
|
||||
sed -i 's/ __attribute__ ((deprecated))//g' $H
|
||||
|
||||
line_num=`grep -n '\*\*\*/' $H | cut -d : -f 1`
|
||||
for x in `seq $line_num`; do
|
||||
sed -i '1d' $H
|
||||
done
|
||||
|
||||
mv $H $H.tmp
|
||||
cat << EOF > $H
|
||||
/*
|
||||
* Copyright 2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
EOF
|
||||
|
||||
cat $H.tmp >> $H
|
||||
|
||||
rm $H.tmp
|
||||
|
||||
echo "Generating udew source..."
|
||||
|
||||
cat << EOF > $C
|
||||
/*
|
||||
* Copyright 2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "udew.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define VC_EXTRALEAN
|
||||
# include <windows.h>
|
||||
|
||||
/* Utility macros. */
|
||||
|
||||
typedef HMODULE DynamicLibrary;
|
||||
|
||||
# define dynamic_library_open(path) LoadLibrary(path)
|
||||
# define dynamic_library_close(lib) FreeLibrary(lib)
|
||||
# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
|
||||
#else
|
||||
# include <dlfcn.h>
|
||||
|
||||
typedef void* DynamicLibrary;
|
||||
|
||||
# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
|
||||
# define dynamic_library_close(lib) dlclose(lib)
|
||||
# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
|
||||
#endif
|
||||
|
||||
#define GLUE(a, b) a ## b
|
||||
|
||||
#define UDEV_LIBRARY_FIND_CHECKED(name) \
|
||||
GLUE(${fp}, name) = (t##name *)dynamic_library_find(lib, #name); \
|
||||
assert(GLUE(${fp}, name));
|
||||
|
||||
#define UDEV_LIBRARY_FIND(name) \
|
||||
GLUE(${fp}, name) = (t##name *)dynamic_library_find(lib, #name);
|
||||
|
||||
static DynamicLibrary lib;
|
||||
|
||||
EOF
|
||||
|
||||
content=`grep --no-filename -ER "extern t" $DIR/include/udew.h`
|
||||
|
||||
echo "$content" | sed -r "s/extern t([a-z0-9_]+).*/t\1 *$fp\1;/gi" >> $C
|
||||
|
||||
cat << EOF >> $C
|
||||
|
||||
static DynamicLibrary dynamic_library_open_find(const char **paths) {
|
||||
int i = 0;
|
||||
while (paths[i] != NULL) {
|
||||
DynamicLibrary lib = dynamic_library_open(paths[i]);
|
||||
if (lib != NULL) {
|
||||
return lib;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void udewExit(void) {
|
||||
if(lib != NULL) {
|
||||
/* Ignore errors. */
|
||||
dynamic_library_close(lib);
|
||||
lib = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation function. */
|
||||
int udewInit(void) {
|
||||
/* Library paths. */
|
||||
#ifdef _WIN32
|
||||
/* Expected in c:/windows/system or similar, no path needed. */
|
||||
const char *paths[] = {"udev.dll", NULL};
|
||||
#elif defined(__APPLE__)
|
||||
/* Default installation path. */
|
||||
const char *paths[] = {"libudev.dylib", NULL};
|
||||
#else
|
||||
const char *paths[] = {"libudev.so",
|
||||
"libudev.so.0",
|
||||
"libudev.so.1",
|
||||
"libudev.so.2",
|
||||
NULL};
|
||||
#endif
|
||||
static int initialized = 0;
|
||||
static int result = 0;
|
||||
int error;
|
||||
|
||||
if (initialized) {
|
||||
return result;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
|
||||
error = atexit(udewExit);
|
||||
if (error) {
|
||||
result = UDEW_ERROR_ATEXIT_FAILED;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Load library. */
|
||||
lib = dynamic_library_open_find(paths);
|
||||
|
||||
if (lib == NULL) {
|
||||
result = UDEW_ERROR_OPEN_FAILED;
|
||||
return result;
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
echo "$content" | sed -r 's/extern t([a-z0-9_]+).*/ UDEV_LIBRARY_FIND(\1);/gi' >> $C
|
||||
|
||||
cat << EOF >> $C
|
||||
|
||||
result = UDEW_SUCCESS;
|
||||
|
||||
return result;
|
||||
}
|
||||
EOF
|
||||
|
||||
if $STUBS; then
|
||||
echo "" >> $C
|
||||
echo "$decl" | while read l; do
|
||||
h=`echo "$l" | sed -r 's/;//' | sed 's/ __attribute__ ((deprecated))//'`
|
||||
echo "$h {" >> $C
|
||||
|
||||
f=`echo $h | sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(.*/\4/i'`
|
||||
args=`echo $h | sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\((.*)\).*?/\5/i'`
|
||||
args=`echo $args | python -c "import sys; l=sys.stdin.readline(); l=l.strip(); print(', '.join([x.split(' ')[-1].replace('*', '') for x in l.split(',')]))"`
|
||||
if [ "$args" = "void" ]; then
|
||||
args=""
|
||||
fi
|
||||
echo " return $fp$f($args);" >> $C
|
||||
echo -e "}\n" >> $C
|
||||
done
|
||||
fi
|
389
extern/udew/include/udew.h
vendored
Normal file
389
extern/udew/include/udew.h
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
#ifndef __UDEW_H__
|
||||
#define __UDEW_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* udev - library context
|
||||
*
|
||||
* reads the udev config and system environment
|
||||
* allows custom logging
|
||||
*/
|
||||
struct udev;
|
||||
typedef struct udev *tudev_ref(struct udev *udev);
|
||||
typedef struct udev *tudev_unref(struct udev *udev);
|
||||
typedef struct udev *tudev_new(void);
|
||||
typedef void tudev_set_log_fn(struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority, const char *file, int line, const char *fn,
|
||||
const char *format, va_list args));
|
||||
typedef int tudev_get_log_priority(struct udev *udev);
|
||||
typedef void tudev_set_log_priority(struct udev *udev, int priority);
|
||||
typedef void *tudev_get_userdata(struct udev *udev);
|
||||
typedef void tudev_set_userdata(struct udev *udev, void *userdata);
|
||||
|
||||
/*
|
||||
* udev_list
|
||||
*
|
||||
* access to libudev generated lists
|
||||
*/
|
||||
struct udev_list_entry;
|
||||
typedef struct udev_list_entry *tudev_list_entry_get_next(struct udev_list_entry *list_entry);
|
||||
typedef struct udev_list_entry *tudev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
|
||||
typedef const char *tudev_list_entry_get_name(struct udev_list_entry *list_entry);
|
||||
typedef const char *tudev_list_entry_get_value(struct udev_list_entry *list_entry);
|
||||
/**
|
||||
* udev_list_entry_foreach:
|
||||
* @list_entry: entry to store the current position
|
||||
* @first_entry: first entry to start with
|
||||
*
|
||||
* Helper to iterate over all entries of a list.
|
||||
*/
|
||||
#define udev_list_entry_foreach(list_entry, first_entry) \
|
||||
for (list_entry = first_entry; \
|
||||
list_entry != NULL; \
|
||||
list_entry = udev_list_entry_get_next(list_entry))
|
||||
|
||||
/*
|
||||
* udev_device
|
||||
*
|
||||
* access to sysfs/kernel devices
|
||||
*/
|
||||
struct udev_device;
|
||||
typedef struct udev_device *tudev_device_ref(struct udev_device *udev_device);
|
||||
typedef struct udev_device *tudev_device_unref(struct udev_device *udev_device);
|
||||
typedef struct udev *tudev_device_get_udev(struct udev_device *udev_device);
|
||||
typedef struct udev_device *tudev_device_new_from_syspath(struct udev *udev, const char *syspath);
|
||||
typedef struct udev_device *tudev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
|
||||
typedef struct udev_device *tudev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
|
||||
typedef struct udev_device *tudev_device_new_from_device_id(struct udev *udev, const char *id);
|
||||
typedef struct udev_device *tudev_device_new_from_environment(struct udev *udev);
|
||||
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
|
||||
typedef struct udev_device *tudev_device_get_parent(struct udev_device *udev_device);
|
||||
typedef struct udev_device *tudev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||
/* retrieve device properties */
|
||||
typedef const char *tudev_device_get_devpath(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_subsystem(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_devtype(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_syspath(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_sysname(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_sysnum(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_devnode(struct udev_device *udev_device);
|
||||
typedef int tudev_device_get_is_initialized(struct udev_device *udev_device);
|
||||
typedef struct udev_list_entry *tudev_device_get_devlinks_list_entry(struct udev_device *udev_device);
|
||||
typedef struct udev_list_entry *tudev_device_get_properties_list_entry(struct udev_device *udev_device);
|
||||
typedef struct udev_list_entry *tudev_device_get_tags_list_entry(struct udev_device *udev_device);
|
||||
typedef struct udev_list_entry *tudev_device_get_sysattr_list_entry(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_property_value(struct udev_device *udev_device, const char *key);
|
||||
typedef const char *tudev_device_get_driver(struct udev_device *udev_device);
|
||||
typedef dev_t tudev_device_get_devnum(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_action(struct udev_device *udev_device);
|
||||
typedef unsigned long long int tudev_device_get_seqnum(struct udev_device *udev_device);
|
||||
typedef unsigned long long int tudev_device_get_usec_since_initialized(struct udev_device *udev_device);
|
||||
typedef const char *tudev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
|
||||
typedef int tudev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
|
||||
typedef int tudev_device_has_tag(struct udev_device *udev_device, const char *tag);
|
||||
|
||||
/*
|
||||
* udev_monitor
|
||||
*
|
||||
* access to kernel uevents and udev events
|
||||
*/
|
||||
struct udev_monitor;
|
||||
typedef struct udev_monitor *tudev_monitor_ref(struct udev_monitor *udev_monitor);
|
||||
typedef struct udev_monitor *tudev_monitor_unref(struct udev_monitor *udev_monitor);
|
||||
typedef struct udev *tudev_monitor_get_udev(struct udev_monitor *udev_monitor);
|
||||
/* kernel and udev generated events over netlink */
|
||||
typedef struct udev_monitor *tudev_monitor_new_from_netlink(struct udev *udev, const char *name);
|
||||
/* bind socket */
|
||||
typedef int tudev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
|
||||
typedef int tudev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
|
||||
typedef int tudev_monitor_get_fd(struct udev_monitor *udev_monitor);
|
||||
typedef struct udev_device *tudev_monitor_receive_device(struct udev_monitor *udev_monitor);
|
||||
/* in-kernel socket filters to select messages that get delivered to a listener */
|
||||
typedef int tudev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
|
||||
const char *subsystem, const char *devtype);
|
||||
typedef int tudev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
|
||||
typedef int tudev_monitor_filter_update(struct udev_monitor *udev_monitor);
|
||||
typedef int tudev_monitor_filter_remove(struct udev_monitor *udev_monitor);
|
||||
|
||||
/*
|
||||
* udev_enumerate
|
||||
*
|
||||
* search sysfs for specific devices and provide a sorted list
|
||||
*/
|
||||
struct udev_enumerate;
|
||||
typedef struct udev_enumerate *tudev_enumerate_ref(struct udev_enumerate *udev_enumerate);
|
||||
typedef struct udev_enumerate *tudev_enumerate_unref(struct udev_enumerate *udev_enumerate);
|
||||
typedef struct udev *tudev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
|
||||
typedef struct udev_enumerate *tudev_enumerate_new(struct udev *udev);
|
||||
/* device properties filter */
|
||||
typedef int tudev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
typedef int tudev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
typedef int tudev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
typedef int tudev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
typedef int tudev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
|
||||
typedef int tudev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
|
||||
typedef int tudev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
|
||||
typedef int tudev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
|
||||
typedef int tudev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
|
||||
typedef int tudev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
|
||||
/* run enumeration with active filters */
|
||||
typedef int tudev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
|
||||
typedef int tudev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
|
||||
/* return device list */
|
||||
typedef struct udev_list_entry *tudev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
|
||||
|
||||
/*
|
||||
* udev_queue
|
||||
*
|
||||
* access to the currently running udev events
|
||||
*/
|
||||
struct udev_queue;
|
||||
typedef struct udev_queue *tudev_queue_ref(struct udev_queue *udev_queue);
|
||||
typedef struct udev_queue *tudev_queue_unref(struct udev_queue *udev_queue);
|
||||
typedef struct udev *tudev_queue_get_udev(struct udev_queue *udev_queue);
|
||||
typedef struct udev_queue *tudev_queue_new(struct udev *udev);
|
||||
typedef unsigned long long int tudev_queue_get_kernel_seqnum(struct udev_queue *udev_queue);
|
||||
typedef unsigned long long int tudev_queue_get_udev_seqnum(struct udev_queue *udev_queue);
|
||||
typedef int tudev_queue_get_udev_is_active(struct udev_queue *udev_queue);
|
||||
typedef int tudev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
|
||||
typedef int tudev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum);
|
||||
typedef int tudev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
|
||||
unsigned long long int start, unsigned long long int end);
|
||||
typedef int tudev_queue_get_fd(struct udev_queue *udev_queue);
|
||||
typedef int tudev_queue_flush(struct udev_queue *udev_queue);
|
||||
typedef struct udev_list_entry *tudev_queue_get_queued_list_entry(struct udev_queue *udev_queue);
|
||||
|
||||
/*
|
||||
* udev_hwdb
|
||||
*
|
||||
* access to the static hardware properties database
|
||||
*/
|
||||
struct udev_hwdb;
|
||||
typedef struct udev_hwdb *tudev_hwdb_new(struct udev *udev);
|
||||
typedef struct udev_hwdb *tudev_hwdb_ref(struct udev_hwdb *hwdb);
|
||||
typedef struct udev_hwdb *tudev_hwdb_unref(struct udev_hwdb *hwdb);
|
||||
typedef struct udev_list_entry *tudev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
|
||||
|
||||
/*
|
||||
* udev_util
|
||||
*
|
||||
* udev specific utilities
|
||||
*/
|
||||
typedef int tudev_util_encode_string(const char *str, char *str_enc, size_t len);
|
||||
|
||||
|
||||
extern tudev_ref *_udev_ref;
|
||||
extern tudev_unref *_udev_unref;
|
||||
extern tudev_new *_udev_new;
|
||||
extern tudev_set_log_fn *_udev_set_log_fn;
|
||||
extern tudev_get_log_priority *_udev_get_log_priority;
|
||||
extern tudev_set_log_priority *_udev_set_log_priority;
|
||||
extern tudev_get_userdata *_udev_get_userdata;
|
||||
extern tudev_set_userdata *_udev_set_userdata;
|
||||
extern tudev_list_entry_get_next *_udev_list_entry_get_next;
|
||||
extern tudev_list_entry_get_by_name *_udev_list_entry_get_by_name;
|
||||
extern tudev_list_entry_get_name *_udev_list_entry_get_name;
|
||||
extern tudev_list_entry_get_value *_udev_list_entry_get_value;
|
||||
extern tudev_device_ref *_udev_device_ref;
|
||||
extern tudev_device_unref *_udev_device_unref;
|
||||
extern tudev_device_get_udev *_udev_device_get_udev;
|
||||
extern tudev_device_new_from_syspath *_udev_device_new_from_syspath;
|
||||
extern tudev_device_new_from_devnum *_udev_device_new_from_devnum;
|
||||
extern tudev_device_new_from_subsystem_sysname *_udev_device_new_from_subsystem_sysname;
|
||||
extern tudev_device_new_from_device_id *_udev_device_new_from_device_id;
|
||||
extern tudev_device_new_from_environment *_udev_device_new_from_environment;
|
||||
extern tudev_device_get_parent *_udev_device_get_parent;
|
||||
extern tudev_device_get_parent_with_subsystem_devtype *_udev_device_get_parent_with_subsystem_devtype;
|
||||
extern tudev_device_get_devpath *_udev_device_get_devpath;
|
||||
extern tudev_device_get_subsystem *_udev_device_get_subsystem;
|
||||
extern tudev_device_get_devtype *_udev_device_get_devtype;
|
||||
extern tudev_device_get_syspath *_udev_device_get_syspath;
|
||||
extern tudev_device_get_sysname *_udev_device_get_sysname;
|
||||
extern tudev_device_get_sysnum *_udev_device_get_sysnum;
|
||||
extern tudev_device_get_devnode *_udev_device_get_devnode;
|
||||
extern tudev_device_get_is_initialized *_udev_device_get_is_initialized;
|
||||
extern tudev_device_get_devlinks_list_entry *_udev_device_get_devlinks_list_entry;
|
||||
extern tudev_device_get_properties_list_entry *_udev_device_get_properties_list_entry;
|
||||
extern tudev_device_get_tags_list_entry *_udev_device_get_tags_list_entry;
|
||||
extern tudev_device_get_sysattr_list_entry *_udev_device_get_sysattr_list_entry;
|
||||
extern tudev_device_get_property_value *_udev_device_get_property_value;
|
||||
extern tudev_device_get_driver *_udev_device_get_driver;
|
||||
extern tudev_device_get_devnum *_udev_device_get_devnum;
|
||||
extern tudev_device_get_action *_udev_device_get_action;
|
||||
extern tudev_device_get_seqnum *_udev_device_get_seqnum;
|
||||
extern tudev_device_get_usec_since_initialized *_udev_device_get_usec_since_initialized;
|
||||
extern tudev_device_get_sysattr_value *_udev_device_get_sysattr_value;
|
||||
extern tudev_device_set_sysattr_value *_udev_device_set_sysattr_value;
|
||||
extern tudev_device_has_tag *_udev_device_has_tag;
|
||||
extern tudev_monitor_ref *_udev_monitor_ref;
|
||||
extern tudev_monitor_unref *_udev_monitor_unref;
|
||||
extern tudev_monitor_get_udev *_udev_monitor_get_udev;
|
||||
extern tudev_monitor_new_from_netlink *_udev_monitor_new_from_netlink;
|
||||
extern tudev_monitor_enable_receiving *_udev_monitor_enable_receiving;
|
||||
extern tudev_monitor_set_receive_buffer_size *_udev_monitor_set_receive_buffer_size;
|
||||
extern tudev_monitor_get_fd *_udev_monitor_get_fd;
|
||||
extern tudev_monitor_receive_device *_udev_monitor_receive_device;
|
||||
extern tudev_monitor_filter_add_match_subsystem_devtype *_udev_monitor_filter_add_match_subsystem_devtype;
|
||||
extern tudev_monitor_filter_add_match_tag *_udev_monitor_filter_add_match_tag;
|
||||
extern tudev_monitor_filter_update *_udev_monitor_filter_update;
|
||||
extern tudev_monitor_filter_remove *_udev_monitor_filter_remove;
|
||||
extern tudev_enumerate_ref *_udev_enumerate_ref;
|
||||
extern tudev_enumerate_unref *_udev_enumerate_unref;
|
||||
extern tudev_enumerate_get_udev *_udev_enumerate_get_udev;
|
||||
extern tudev_enumerate_new *_udev_enumerate_new;
|
||||
extern tudev_enumerate_add_match_subsystem *_udev_enumerate_add_match_subsystem;
|
||||
extern tudev_enumerate_add_nomatch_subsystem *_udev_enumerate_add_nomatch_subsystem;
|
||||
extern tudev_enumerate_add_match_sysattr *_udev_enumerate_add_match_sysattr;
|
||||
extern tudev_enumerate_add_nomatch_sysattr *_udev_enumerate_add_nomatch_sysattr;
|
||||
extern tudev_enumerate_add_match_property *_udev_enumerate_add_match_property;
|
||||
extern tudev_enumerate_add_match_sysname *_udev_enumerate_add_match_sysname;
|
||||
extern tudev_enumerate_add_match_tag *_udev_enumerate_add_match_tag;
|
||||
extern tudev_enumerate_add_match_parent *_udev_enumerate_add_match_parent;
|
||||
extern tudev_enumerate_add_match_is_initialized *_udev_enumerate_add_match_is_initialized;
|
||||
extern tudev_enumerate_add_syspath *_udev_enumerate_add_syspath;
|
||||
extern tudev_enumerate_scan_devices *_udev_enumerate_scan_devices;
|
||||
extern tudev_enumerate_scan_subsystems *_udev_enumerate_scan_subsystems;
|
||||
extern tudev_enumerate_get_list_entry *_udev_enumerate_get_list_entry;
|
||||
extern tudev_queue_ref *_udev_queue_ref;
|
||||
extern tudev_queue_unref *_udev_queue_unref;
|
||||
extern tudev_queue_get_udev *_udev_queue_get_udev;
|
||||
extern tudev_queue_new *_udev_queue_new;
|
||||
extern tudev_queue_get_kernel_seqnum *_udev_queue_get_kernel_seqnum;
|
||||
extern tudev_queue_get_udev_seqnum *_udev_queue_get_udev_seqnum;
|
||||
extern tudev_queue_get_udev_is_active *_udev_queue_get_udev_is_active;
|
||||
extern tudev_queue_get_queue_is_empty *_udev_queue_get_queue_is_empty;
|
||||
extern tudev_queue_get_seqnum_is_finished *_udev_queue_get_seqnum_is_finished;
|
||||
extern tudev_queue_get_seqnum_sequence_is_finished *_udev_queue_get_seqnum_sequence_is_finished;
|
||||
extern tudev_queue_get_fd *_udev_queue_get_fd;
|
||||
extern tudev_queue_flush *_udev_queue_flush;
|
||||
extern tudev_queue_get_queued_list_entry *_udev_queue_get_queued_list_entry;
|
||||
extern tudev_hwdb_new *_udev_hwdb_new;
|
||||
extern tudev_hwdb_ref *_udev_hwdb_ref;
|
||||
extern tudev_hwdb_unref *_udev_hwdb_unref;
|
||||
extern tudev_hwdb_get_properties_list_entry *_udev_hwdb_get_properties_list_entry;
|
||||
extern tudev_util_encode_string *_udev_util_encode_string;
|
||||
|
||||
enum {
|
||||
UDEW_SUCCESS = 0,
|
||||
UDEW_ERROR_OPEN_FAILED = -1,
|
||||
UDEW_ERROR_ATEXIT_FAILED = -2,
|
||||
};
|
||||
|
||||
int udewInit(void);
|
||||
|
||||
struct udev *udev_ref(struct udev *udev);
|
||||
struct udev *udev_unref(struct udev *udev);
|
||||
struct udev *udev_new(void);
|
||||
int udev_get_log_priority(struct udev *udev);
|
||||
void udev_set_log_priority(struct udev *udev, int priority);
|
||||
void *udev_get_userdata(struct udev *udev);
|
||||
void udev_set_userdata(struct udev *udev, void *userdata);
|
||||
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
|
||||
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
|
||||
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
|
||||
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
|
||||
struct udev_device *udev_device_ref(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_unref(struct udev_device *udev_device);
|
||||
struct udev *udev_device_get_udev(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
|
||||
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
|
||||
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
|
||||
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
|
||||
struct udev_device *udev_device_new_from_environment(struct udev *udev);
|
||||
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||
const char *udev_device_get_devpath(struct udev_device *udev_device);
|
||||
const char *udev_device_get_subsystem(struct udev_device *udev_device);
|
||||
const char *udev_device_get_devtype(struct udev_device *udev_device);
|
||||
const char *udev_device_get_syspath(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysname(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysnum(struct udev_device *udev_device);
|
||||
const char *udev_device_get_devnode(struct udev_device *udev_device);
|
||||
int udev_device_get_is_initialized(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
|
||||
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
|
||||
const char *udev_device_get_driver(struct udev_device *udev_device);
|
||||
dev_t udev_device_get_devnum(struct udev_device *udev_device);
|
||||
const char *udev_device_get_action(struct udev_device *udev_device);
|
||||
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
|
||||
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
|
||||
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
|
||||
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
|
||||
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
|
||||
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
|
||||
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
|
||||
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
|
||||
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
|
||||
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
|
||||
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
|
||||
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
|
||||
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
|
||||
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
|
||||
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
|
||||
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
|
||||
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
|
||||
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
|
||||
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
|
||||
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
|
||||
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
|
||||
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_new(struct udev *udev);
|
||||
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue);
|
||||
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum);
|
||||
int udev_queue_get_fd(struct udev_queue *udev_queue);
|
||||
int udev_queue_flush(struct udev_queue *udev_queue);
|
||||
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue);
|
||||
struct udev_hwdb *udev_hwdb_new(struct udev *udev);
|
||||
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
|
||||
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
|
||||
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
|
||||
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
656
extern/udew/src/udew.c
vendored
Normal file
656
extern/udew/src/udew.c
vendored
Normal file
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* Copyright 2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "udew.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define VC_EXTRALEAN
|
||||
# include <windows.h>
|
||||
|
||||
/* Utility macros. */
|
||||
|
||||
typedef HMODULE DynamicLibrary;
|
||||
|
||||
# define dynamic_library_open(path) LoadLibrary(path)
|
||||
# define dynamic_library_close(lib) FreeLibrary(lib)
|
||||
# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
|
||||
#else
|
||||
# include <dlfcn.h>
|
||||
|
||||
typedef void* DynamicLibrary;
|
||||
|
||||
# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
|
||||
# define dynamic_library_close(lib) dlclose(lib)
|
||||
# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
|
||||
#endif
|
||||
|
||||
#define GLUE(a, b) a ## b
|
||||
|
||||
#define UDEV_LIBRARY_FIND_CHECKED(name) GLUE(_, name) = (t##name *)dynamic_library_find(lib, #name); assert(GLUE(_, name));
|
||||
|
||||
#define UDEV_LIBRARY_FIND(name) GLUE(_, name) = (t##name *)dynamic_library_find(lib, #name);
|
||||
|
||||
static DynamicLibrary lib;
|
||||
|
||||
tudev_ref *_udev_ref;
|
||||
tudev_unref *_udev_unref;
|
||||
tudev_new *_udev_new;
|
||||
tudev_set_log_fn *_udev_set_log_fn;
|
||||
tudev_get_log_priority *_udev_get_log_priority;
|
||||
tudev_set_log_priority *_udev_set_log_priority;
|
||||
tudev_get_userdata *_udev_get_userdata;
|
||||
tudev_set_userdata *_udev_set_userdata;
|
||||
tudev_list_entry_get_next *_udev_list_entry_get_next;
|
||||
tudev_list_entry_get_by_name *_udev_list_entry_get_by_name;
|
||||
tudev_list_entry_get_name *_udev_list_entry_get_name;
|
||||
tudev_list_entry_get_value *_udev_list_entry_get_value;
|
||||
tudev_device_ref *_udev_device_ref;
|
||||
tudev_device_unref *_udev_device_unref;
|
||||
tudev_device_get_udev *_udev_device_get_udev;
|
||||
tudev_device_new_from_syspath *_udev_device_new_from_syspath;
|
||||
tudev_device_new_from_devnum *_udev_device_new_from_devnum;
|
||||
tudev_device_new_from_subsystem_sysname *_udev_device_new_from_subsystem_sysname;
|
||||
tudev_device_new_from_device_id *_udev_device_new_from_device_id;
|
||||
tudev_device_new_from_environment *_udev_device_new_from_environment;
|
||||
tudev_device_get_parent *_udev_device_get_parent;
|
||||
tudev_device_get_parent_with_subsystem_devtype *_udev_device_get_parent_with_subsystem_devtype;
|
||||
tudev_device_get_devpath *_udev_device_get_devpath;
|
||||
tudev_device_get_subsystem *_udev_device_get_subsystem;
|
||||
tudev_device_get_devtype *_udev_device_get_devtype;
|
||||
tudev_device_get_syspath *_udev_device_get_syspath;
|
||||
tudev_device_get_sysname *_udev_device_get_sysname;
|
||||
tudev_device_get_sysnum *_udev_device_get_sysnum;
|
||||
tudev_device_get_devnode *_udev_device_get_devnode;
|
||||
tudev_device_get_is_initialized *_udev_device_get_is_initialized;
|
||||
tudev_device_get_devlinks_list_entry *_udev_device_get_devlinks_list_entry;
|
||||
tudev_device_get_properties_list_entry *_udev_device_get_properties_list_entry;
|
||||
tudev_device_get_tags_list_entry *_udev_device_get_tags_list_entry;
|
||||
tudev_device_get_sysattr_list_entry *_udev_device_get_sysattr_list_entry;
|
||||
tudev_device_get_property_value *_udev_device_get_property_value;
|
||||
tudev_device_get_driver *_udev_device_get_driver;
|
||||
tudev_device_get_devnum *_udev_device_get_devnum;
|
||||
tudev_device_get_action *_udev_device_get_action;
|
||||
tudev_device_get_seqnum *_udev_device_get_seqnum;
|
||||
tudev_device_get_usec_since_initialized *_udev_device_get_usec_since_initialized;
|
||||
tudev_device_get_sysattr_value *_udev_device_get_sysattr_value;
|
||||
tudev_device_set_sysattr_value *_udev_device_set_sysattr_value;
|
||||
tudev_device_has_tag *_udev_device_has_tag;
|
||||
tudev_monitor_ref *_udev_monitor_ref;
|
||||
tudev_monitor_unref *_udev_monitor_unref;
|
||||
tudev_monitor_get_udev *_udev_monitor_get_udev;
|
||||
tudev_monitor_new_from_netlink *_udev_monitor_new_from_netlink;
|
||||
tudev_monitor_enable_receiving *_udev_monitor_enable_receiving;
|
||||
tudev_monitor_set_receive_buffer_size *_udev_monitor_set_receive_buffer_size;
|
||||
tudev_monitor_get_fd *_udev_monitor_get_fd;
|
||||
tudev_monitor_receive_device *_udev_monitor_receive_device;
|
||||
tudev_monitor_filter_add_match_subsystem_devtype *_udev_monitor_filter_add_match_subsystem_devtype;
|
||||
tudev_monitor_filter_add_match_tag *_udev_monitor_filter_add_match_tag;
|
||||
tudev_monitor_filter_update *_udev_monitor_filter_update;
|
||||
tudev_monitor_filter_remove *_udev_monitor_filter_remove;
|
||||
tudev_enumerate_ref *_udev_enumerate_ref;
|
||||
tudev_enumerate_unref *_udev_enumerate_unref;
|
||||
tudev_enumerate_get_udev *_udev_enumerate_get_udev;
|
||||
tudev_enumerate_new *_udev_enumerate_new;
|
||||
tudev_enumerate_add_match_subsystem *_udev_enumerate_add_match_subsystem;
|
||||
tudev_enumerate_add_nomatch_subsystem *_udev_enumerate_add_nomatch_subsystem;
|
||||
tudev_enumerate_add_match_sysattr *_udev_enumerate_add_match_sysattr;
|
||||
tudev_enumerate_add_nomatch_sysattr *_udev_enumerate_add_nomatch_sysattr;
|
||||
tudev_enumerate_add_match_property *_udev_enumerate_add_match_property;
|
||||
tudev_enumerate_add_match_sysname *_udev_enumerate_add_match_sysname;
|
||||
tudev_enumerate_add_match_tag *_udev_enumerate_add_match_tag;
|
||||
tudev_enumerate_add_match_parent *_udev_enumerate_add_match_parent;
|
||||
tudev_enumerate_add_match_is_initialized *_udev_enumerate_add_match_is_initialized;
|
||||
tudev_enumerate_add_syspath *_udev_enumerate_add_syspath;
|
||||
tudev_enumerate_scan_devices *_udev_enumerate_scan_devices;
|
||||
tudev_enumerate_scan_subsystems *_udev_enumerate_scan_subsystems;
|
||||
tudev_enumerate_get_list_entry *_udev_enumerate_get_list_entry;
|
||||
tudev_queue_ref *_udev_queue_ref;
|
||||
tudev_queue_unref *_udev_queue_unref;
|
||||
tudev_queue_get_udev *_udev_queue_get_udev;
|
||||
tudev_queue_new *_udev_queue_new;
|
||||
tudev_queue_get_kernel_seqnum *_udev_queue_get_kernel_seqnum;
|
||||
tudev_queue_get_udev_seqnum *_udev_queue_get_udev_seqnum;
|
||||
tudev_queue_get_udev_is_active *_udev_queue_get_udev_is_active;
|
||||
tudev_queue_get_queue_is_empty *_udev_queue_get_queue_is_empty;
|
||||
tudev_queue_get_seqnum_is_finished *_udev_queue_get_seqnum_is_finished;
|
||||
tudev_queue_get_seqnum_sequence_is_finished *_udev_queue_get_seqnum_sequence_is_finished;
|
||||
tudev_queue_get_fd *_udev_queue_get_fd;
|
||||
tudev_queue_flush *_udev_queue_flush;
|
||||
tudev_queue_get_queued_list_entry *_udev_queue_get_queued_list_entry;
|
||||
tudev_hwdb_new *_udev_hwdb_new;
|
||||
tudev_hwdb_ref *_udev_hwdb_ref;
|
||||
tudev_hwdb_unref *_udev_hwdb_unref;
|
||||
tudev_hwdb_get_properties_list_entry *_udev_hwdb_get_properties_list_entry;
|
||||
tudev_util_encode_string *_udev_util_encode_string;
|
||||
|
||||
static DynamicLibrary dynamic_library_open_find(const char **paths) {
|
||||
int i = 0;
|
||||
while (paths[i] != NULL) {
|
||||
DynamicLibrary lib = dynamic_library_open(paths[i]);
|
||||
if (lib != NULL) {
|
||||
return lib;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void udewExit(void) {
|
||||
if(lib != NULL) {
|
||||
/* Ignore errors. */
|
||||
dynamic_library_close(lib);
|
||||
lib = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation function. */
|
||||
int udewInit(void) {
|
||||
/* Library paths. */
|
||||
#ifdef _WIN32
|
||||
/* Expected in c:/windows/system or similar, no path needed. */
|
||||
const char *paths[] = {"udev.dll", NULL};
|
||||
#elif defined(__APPLE__)
|
||||
/* Default installation path. */
|
||||
const char *paths[] = {"libudev.dylib", NULL};
|
||||
#else
|
||||
const char *paths[] = {"libudev.so",
|
||||
"libudev.so.0",
|
||||
"libudev.so.1",
|
||||
"libudev.so.2",
|
||||
NULL};
|
||||
#endif
|
||||
static int initialized = 0;
|
||||
static int result = 0;
|
||||
int error;
|
||||
|
||||
if (initialized) {
|
||||
return result;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
|
||||
error = atexit(udewExit);
|
||||
if (error) {
|
||||
result = UDEW_ERROR_ATEXIT_FAILED;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Load library. */
|
||||
lib = dynamic_library_open_find(paths);
|
||||
|
||||
if (lib == NULL) {
|
||||
result = UDEW_ERROR_OPEN_FAILED;
|
||||
return result;
|
||||
}
|
||||
|
||||
UDEV_LIBRARY_FIND(udev_ref);
|
||||
UDEV_LIBRARY_FIND(udev_unref);
|
||||
UDEV_LIBRARY_FIND(udev_new);
|
||||
UDEV_LIBRARY_FIND(udev_set_log_fn);
|
||||
UDEV_LIBRARY_FIND(udev_get_log_priority);
|
||||
UDEV_LIBRARY_FIND(udev_set_log_priority);
|
||||
UDEV_LIBRARY_FIND(udev_get_userdata);
|
||||
UDEV_LIBRARY_FIND(udev_set_userdata);
|
||||
UDEV_LIBRARY_FIND(udev_list_entry_get_next);
|
||||
UDEV_LIBRARY_FIND(udev_list_entry_get_by_name);
|
||||
UDEV_LIBRARY_FIND(udev_list_entry_get_name);
|
||||
UDEV_LIBRARY_FIND(udev_list_entry_get_value);
|
||||
UDEV_LIBRARY_FIND(udev_device_ref);
|
||||
UDEV_LIBRARY_FIND(udev_device_unref);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_udev);
|
||||
UDEV_LIBRARY_FIND(udev_device_new_from_syspath);
|
||||
UDEV_LIBRARY_FIND(udev_device_new_from_devnum);
|
||||
UDEV_LIBRARY_FIND(udev_device_new_from_subsystem_sysname);
|
||||
UDEV_LIBRARY_FIND(udev_device_new_from_device_id);
|
||||
UDEV_LIBRARY_FIND(udev_device_new_from_environment);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_parent);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_parent_with_subsystem_devtype);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_devpath);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_subsystem);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_devtype);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_syspath);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_sysname);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_sysnum);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_devnode);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_is_initialized);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_devlinks_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_properties_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_tags_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_sysattr_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_property_value);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_driver);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_devnum);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_action);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_seqnum);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_usec_since_initialized);
|
||||
UDEV_LIBRARY_FIND(udev_device_get_sysattr_value);
|
||||
UDEV_LIBRARY_FIND(udev_device_set_sysattr_value);
|
||||
UDEV_LIBRARY_FIND(udev_device_has_tag);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_ref);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_unref);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_get_udev);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_new_from_netlink);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_enable_receiving);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_set_receive_buffer_size);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_get_fd);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_receive_device);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_filter_add_match_subsystem_devtype);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_filter_add_match_tag);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_filter_update);
|
||||
UDEV_LIBRARY_FIND(udev_monitor_filter_remove);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_ref);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_unref);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_get_udev);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_new);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_subsystem);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_nomatch_subsystem);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_sysattr);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_nomatch_sysattr);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_property);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_sysname);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_tag);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_parent);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_match_is_initialized);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_add_syspath);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_scan_devices);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_scan_subsystems);
|
||||
UDEV_LIBRARY_FIND(udev_enumerate_get_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_queue_ref);
|
||||
UDEV_LIBRARY_FIND(udev_queue_unref);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_udev);
|
||||
UDEV_LIBRARY_FIND(udev_queue_new);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_kernel_seqnum);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_udev_seqnum);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_udev_is_active);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_queue_is_empty);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_seqnum_is_finished);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_seqnum_sequence_is_finished);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_fd);
|
||||
UDEV_LIBRARY_FIND(udev_queue_flush);
|
||||
UDEV_LIBRARY_FIND(udev_queue_get_queued_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_hwdb_new);
|
||||
UDEV_LIBRARY_FIND(udev_hwdb_ref);
|
||||
UDEV_LIBRARY_FIND(udev_hwdb_unref);
|
||||
UDEV_LIBRARY_FIND(udev_hwdb_get_properties_list_entry);
|
||||
UDEV_LIBRARY_FIND(udev_util_encode_string);
|
||||
|
||||
result = UDEW_SUCCESS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct udev *udev_ref(struct udev *udev) {
|
||||
return _udev_ref(udev);
|
||||
}
|
||||
|
||||
struct udev *udev_unref(struct udev *udev) {
|
||||
return _udev_unref(udev);
|
||||
}
|
||||
|
||||
struct udev *udev_new(void) {
|
||||
return _udev_new();
|
||||
}
|
||||
|
||||
int udev_get_log_priority(struct udev *udev) {
|
||||
return _udev_get_log_priority(udev);
|
||||
}
|
||||
|
||||
void udev_set_log_priority(struct udev *udev, int priority) {
|
||||
return _udev_set_log_priority(udev, priority);
|
||||
}
|
||||
|
||||
void *udev_get_userdata(struct udev *udev) {
|
||||
return _udev_get_userdata(udev);
|
||||
}
|
||||
|
||||
void udev_set_userdata(struct udev *udev, void *userdata) {
|
||||
return _udev_set_userdata(udev, userdata);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) {
|
||||
return _udev_list_entry_get_next(list_entry);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) {
|
||||
return _udev_list_entry_get_by_name(list_entry, name);
|
||||
}
|
||||
|
||||
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) {
|
||||
return _udev_list_entry_get_name(list_entry);
|
||||
}
|
||||
|
||||
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) {
|
||||
return _udev_list_entry_get_value(list_entry);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_ref(struct udev_device *udev_device) {
|
||||
return _udev_device_ref(udev_device);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_unref(struct udev_device *udev_device) {
|
||||
return _udev_device_unref(udev_device);
|
||||
}
|
||||
|
||||
struct udev *udev_device_get_udev(struct udev_device *udev_device) {
|
||||
return _udev_device_get_udev(udev_device);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
|
||||
return _udev_device_new_from_syspath(udev, syspath);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) {
|
||||
return _udev_device_new_from_devnum(udev, type, devnum);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) {
|
||||
return _udev_device_new_from_subsystem_sysname(udev, subsystem, sysname);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) {
|
||||
return _udev_device_new_from_device_id(udev, id);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new_from_environment(struct udev *udev) {
|
||||
return _udev_device_new_from_environment(udev);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_get_parent(struct udev_device *udev_device) {
|
||||
return _udev_device_get_parent(udev_device);
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) {
|
||||
return _udev_device_get_parent_with_subsystem_devtype(udev_device, subsystem, devtype);
|
||||
}
|
||||
|
||||
const char *udev_device_get_devpath(struct udev_device *udev_device) {
|
||||
return _udev_device_get_devpath(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_subsystem(struct udev_device *udev_device) {
|
||||
return _udev_device_get_subsystem(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_devtype(struct udev_device *udev_device) {
|
||||
return _udev_device_get_devtype(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_syspath(struct udev_device *udev_device) {
|
||||
return _udev_device_get_syspath(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_sysname(struct udev_device *udev_device) {
|
||||
return _udev_device_get_sysname(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_sysnum(struct udev_device *udev_device) {
|
||||
return _udev_device_get_sysnum(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_devnode(struct udev_device *udev_device) {
|
||||
return _udev_device_get_devnode(udev_device);
|
||||
}
|
||||
|
||||
int udev_device_get_is_initialized(struct udev_device *udev_device) {
|
||||
return _udev_device_get_is_initialized(udev_device);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) {
|
||||
return _udev_device_get_devlinks_list_entry(udev_device);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) {
|
||||
return _udev_device_get_properties_list_entry(udev_device);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) {
|
||||
return _udev_device_get_tags_list_entry(udev_device);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) {
|
||||
return _udev_device_get_sysattr_list_entry(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) {
|
||||
return _udev_device_get_property_value(udev_device, key);
|
||||
}
|
||||
|
||||
const char *udev_device_get_driver(struct udev_device *udev_device) {
|
||||
return _udev_device_get_driver(udev_device);
|
||||
}
|
||||
|
||||
dev_t udev_device_get_devnum(struct udev_device *udev_device) {
|
||||
return _udev_device_get_devnum(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_action(struct udev_device *udev_device) {
|
||||
return _udev_device_get_action(udev_device);
|
||||
}
|
||||
|
||||
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) {
|
||||
return _udev_device_get_seqnum(udev_device);
|
||||
}
|
||||
|
||||
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) {
|
||||
return _udev_device_get_usec_since_initialized(udev_device);
|
||||
}
|
||||
|
||||
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) {
|
||||
return _udev_device_get_sysattr_value(udev_device, sysattr);
|
||||
}
|
||||
|
||||
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value) {
|
||||
return _udev_device_set_sysattr_value(udev_device, sysattr, value);
|
||||
}
|
||||
|
||||
int udev_device_has_tag(struct udev_device *udev_device, const char *tag) {
|
||||
return _udev_device_has_tag(udev_device, tag);
|
||||
}
|
||||
|
||||
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_ref(udev_monitor);
|
||||
}
|
||||
|
||||
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_unref(udev_monitor);
|
||||
}
|
||||
|
||||
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_get_udev(udev_monitor);
|
||||
}
|
||||
|
||||
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) {
|
||||
return _udev_monitor_new_from_netlink(udev, name);
|
||||
}
|
||||
|
||||
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_enable_receiving(udev_monitor);
|
||||
}
|
||||
|
||||
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) {
|
||||
return _udev_monitor_set_receive_buffer_size(udev_monitor, size);
|
||||
}
|
||||
|
||||
int udev_monitor_get_fd(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_get_fd(udev_monitor);
|
||||
}
|
||||
|
||||
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_receive_device(udev_monitor);
|
||||
}
|
||||
|
||||
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) {
|
||||
return _udev_monitor_filter_add_match_tag(udev_monitor, tag);
|
||||
}
|
||||
|
||||
int udev_monitor_filter_update(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_filter_update(udev_monitor);
|
||||
}
|
||||
|
||||
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) {
|
||||
return _udev_monitor_filter_remove(udev_monitor);
|
||||
}
|
||||
|
||||
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_ref(udev_enumerate);
|
||||
}
|
||||
|
||||
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_unref(udev_enumerate);
|
||||
}
|
||||
|
||||
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_get_udev(udev_enumerate);
|
||||
}
|
||||
|
||||
struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
|
||||
return _udev_enumerate_new(udev);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
|
||||
return _udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
|
||||
return _udev_enumerate_add_nomatch_subsystem(udev_enumerate, subsystem);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
|
||||
return _udev_enumerate_add_match_sysattr(udev_enumerate, sysattr, value);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
|
||||
return _udev_enumerate_add_nomatch_sysattr(udev_enumerate, sysattr, value);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
|
||||
return _udev_enumerate_add_match_property(udev_enumerate, property, value);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
|
||||
return _udev_enumerate_add_match_sysname(udev_enumerate, sysname);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
|
||||
return _udev_enumerate_add_match_tag(udev_enumerate, tag);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
|
||||
return _udev_enumerate_add_match_parent(udev_enumerate, parent);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_add_match_is_initialized(udev_enumerate);
|
||||
}
|
||||
|
||||
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
|
||||
return _udev_enumerate_add_syspath(udev_enumerate, syspath);
|
||||
}
|
||||
|
||||
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_scan_devices(udev_enumerate);
|
||||
}
|
||||
|
||||
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_scan_subsystems(udev_enumerate);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
|
||||
return _udev_enumerate_get_list_entry(udev_enumerate);
|
||||
}
|
||||
|
||||
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_ref(udev_queue);
|
||||
}
|
||||
|
||||
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_unref(udev_queue);
|
||||
}
|
||||
|
||||
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_udev(udev_queue);
|
||||
}
|
||||
|
||||
struct udev_queue *udev_queue_new(struct udev *udev) {
|
||||
return _udev_queue_new(udev);
|
||||
}
|
||||
|
||||
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_kernel_seqnum(udev_queue);
|
||||
}
|
||||
|
||||
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_udev_seqnum(udev_queue);
|
||||
}
|
||||
|
||||
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_udev_is_active(udev_queue);
|
||||
}
|
||||
|
||||
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_queue_is_empty(udev_queue);
|
||||
}
|
||||
|
||||
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) {
|
||||
return _udev_queue_get_seqnum_is_finished(udev_queue, seqnum);
|
||||
}
|
||||
|
||||
int udev_queue_get_fd(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_fd(udev_queue);
|
||||
}
|
||||
|
||||
int udev_queue_flush(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_flush(udev_queue);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
|
||||
return _udev_queue_get_queued_list_entry(udev_queue);
|
||||
}
|
||||
|
||||
struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
|
||||
return _udev_hwdb_new(udev);
|
||||
}
|
||||
|
||||
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
|
||||
return _udev_hwdb_ref(hwdb);
|
||||
}
|
||||
|
||||
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
|
||||
return _udev_hwdb_unref(hwdb);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) {
|
||||
return _udev_hwdb_get_properties_list_entry(hwdb, modalias, flags);
|
||||
}
|
||||
|
||||
int udev_util_encode_string(const char *str, char *str_enc, size_t len) {
|
||||
return _udev_util_encode_string(str, str_enc, len);
|
||||
}
|
||||
|
@@ -563,7 +563,7 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
|
||||
row.label(text="File Suffix:")
|
||||
row.prop(rv, "file_suffix", text="")
|
||||
|
||||
else:
|
||||
elif rd.views_format == 'MULTIVIEW':
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
|
||||
|
||||
@@ -574,6 +574,23 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
|
||||
row = layout.row()
|
||||
row.label(text="Camera Suffix:")
|
||||
row.prop(rv, "camera_suffix", text="")
|
||||
else:
|
||||
wm = context.window_manager
|
||||
|
||||
running = scene.hmd_running
|
||||
text_win = "Close HMD Window" if wm.has_hmd_window else "Open HMD Window"
|
||||
text_run = "Stop Session" if running else "Start Session"
|
||||
icon = 'PAUSE' if running else 'PLAY'
|
||||
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.operator("wm.hmd_view_toggle", text=text_win)
|
||||
row.operator("wm.hmd_session_run", text=text_run, icon=icon)
|
||||
|
||||
col.prop(rd, "hmd_camlock")
|
||||
col.prop(rd, "use_hmd_view_lensdist", text="Lens Distortion")
|
||||
col.prop(rd, "hmd_view_shade", text="Shading")
|
||||
|
||||
|
||||
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
|
||||
|
@@ -112,6 +112,39 @@ if(WITH_INPUT_NDOF)
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if (WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
if(WITH_OPENHMD)
|
||||
add_definitions(-DWITH_OPENHMD)
|
||||
if(WITH_OPENHMD_DYNLOAD)
|
||||
add_definitions(-DWITH_OPENHMD_DYNLOAD)
|
||||
list(APPEND INC
|
||||
../../extern/udew/include
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DOHMD_STATIC)
|
||||
endif(WIN32)
|
||||
|
||||
list(APPEND INC
|
||||
../../extern/openhmd
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_OpenHMDManager.h
|
||||
intern/GHOST_OpenHMDManager.cpp
|
||||
intern/GHOST_EventOpenHMD.h
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${OPENHMD_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if(WITH_HEADLESS OR WITH_GHOST_SDL)
|
||||
if(WITH_HEADLESS)
|
||||
list(APPEND SRC
|
||||
|
@@ -937,6 +937,24 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
|
||||
*/
|
||||
extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
|
||||
|
||||
extern int GHOST_HMDgetNumDevices(void);
|
||||
extern void GHOST_HMDopenDevice(int index);
|
||||
extern void GHOST_HMDcloseDevice(void);
|
||||
extern int GHOST_HMDgetOpenDeviceIndex(void);
|
||||
extern const char *GHOST_HMDgetDeviceName(int index);
|
||||
extern const char *GHOST_HMDgetVendorName(int index);
|
||||
extern float GHOST_HMDgetDeviceIPD(void);
|
||||
extern void GHOST_HMDsetDeviceIPD(float value);
|
||||
extern float GHOST_HMDgetLensHorizontalSeparation(void);
|
||||
extern float GHOST_HMDgetProjectionZNear(void);
|
||||
extern float GHOST_HMDgetProjectionZFar(void);
|
||||
extern float GHOST_HMDgetScreenHorizontalSize(void);
|
||||
extern float GHOST_HMDgetLeftEyeFOV(void);
|
||||
extern float GHOST_HMDgetRightEyeFOV(void);
|
||||
extern void GHOST_HMDgetLeftModelviewMatrix(float r_mat[4][4]);
|
||||
extern void GHOST_HMDgetRightModelviewMatrix(float r_mat[4][4]);
|
||||
extern void* GHOST_HMDgetDistortionParameters(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
class GHOST_IEventConsumer;
|
||||
class GHOST_OpenHMDManager;
|
||||
|
||||
/**
|
||||
* \page GHOSTPage GHOST
|
||||
@@ -385,6 +386,11 @@ public:
|
||||
virtual void setNDOFDeadZone(float deadzone) = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \return A pointer to our OpenHMD manager.
|
||||
*/
|
||||
virtual GHOST_OpenHMDManager *getOpenHMDManager() const = 0;
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* \param action
|
||||
|
@@ -205,6 +205,8 @@ typedef enum {
|
||||
GHOST_kEventImeComposition,
|
||||
GHOST_kEventImeCompositionEnd,
|
||||
|
||||
GHOST_kEventHMD, // HMD - head mounted device (virtual reality)
|
||||
|
||||
GHOST_kNumEventTypes
|
||||
} GHOST_TEventType;
|
||||
|
||||
@@ -522,6 +524,16 @@ typedef struct {
|
||||
char utf8_buf[6];
|
||||
} GHOST_TEventKeyData;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kOrientationUpdate,
|
||||
GHOST_kDeviceNumChanged,
|
||||
} GHOST_TEventOpenHMDSubTypes;
|
||||
|
||||
typedef struct {
|
||||
GHOST_TEventOpenHMDSubTypes subtype;
|
||||
float orientation[4]; // Orientation quaternion of the HMD (only for subtype GHOST_kOrientationUpdate)
|
||||
} GHOST_TEventOpenHMDData;
|
||||
|
||||
typedef struct {
|
||||
/** Number of pixels on a line. */
|
||||
GHOST_TUns32 xPixels;
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "GHOST_ISystem.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
#include "GHOST_OpenHMDManager.h"
|
||||
#include "intern/GHOST_CallbackEventConsumer.h"
|
||||
|
||||
GHOST_SystemHandle GHOST_CreateSystem(void)
|
||||
@@ -938,3 +939,204 @@ void GHOST_EndIME(GHOST_WindowHandle windowhandle)
|
||||
}
|
||||
|
||||
#endif /* WITH_INPUT_IME */
|
||||
|
||||
#ifdef WITH_INPUT_HMD
|
||||
|
||||
int GHOST_HMDgetNumDevices()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getNumDevices();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GHOST_HMDopenDevice(int index)
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
ohmd->openDevice(index);
|
||||
#else
|
||||
(void)index;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GHOST_HMDcloseDevice()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
ohmd->closeDevice();
|
||||
#endif
|
||||
}
|
||||
|
||||
int GHOST_HMDgetOpenDeviceIndex()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getDeviceIndex();
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *GHOST_HMDgetDeviceName(int index)
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getDeviceName(index);
|
||||
#else
|
||||
(void)index;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *GHOST_HMDgetVendorName(int index)
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getVendorName(index);
|
||||
#else
|
||||
(void)index;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetDeviceIPD()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getEyeIPD();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GHOST_HMDsetDeviceIPD(float value)
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
ohmd->setEyeIPD(value);
|
||||
#else
|
||||
(void)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetLensHorizontalSeparation()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getLensHorizontalSeparation();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetProjectionZNear()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getProjectionZNear();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetProjectionZFar()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getProjectionZFar();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetScreenHorizontalSize()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getScreenHorizontalSize();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetLeftEyeFOV()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getLeftEyeFOV();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
float GHOST_HMDgetRightEyeFOV()
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getRightEyeFOV();
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WITH_OPENHMD
|
||||
static void ghost_UnitMat(float r_mat[4][4])
|
||||
{
|
||||
r_mat[0][0] = r_mat[1][1] = r_mat[2][2] = r_mat[3][3] = 1.0f;
|
||||
r_mat[0][1] = r_mat[0][2] = r_mat[0][3] = 0.0f;
|
||||
r_mat[1][0] = r_mat[1][2] = r_mat[1][3] = 0.0f;
|
||||
r_mat[2][0] = r_mat[2][1] = r_mat[2][3] = 0.0f;
|
||||
r_mat[3][0] = r_mat[3][1] = r_mat[3][2] = 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GHOST_HMDgetLeftModelviewMatrix(float r_mat[4][4])
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
ohmd->getLeftEyeGLModelviewMatrix(r_mat);
|
||||
#else
|
||||
ghost_UnitMat(r_mat);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GHOST_HMDgetRightModelviewMatrix(float r_mat[4][4])
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
ohmd->getRightEyeGLModelviewMatrix(r_mat);
|
||||
#else
|
||||
ghost_UnitMat(r_mat);
|
||||
#endif
|
||||
}
|
||||
|
||||
void* GHOST_HMDgetDistortionParameters(void)
|
||||
{
|
||||
#ifdef WITH_OPENHMD
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager();
|
||||
return ohmd->getDistortionParameters();
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* WITH_INPUT_HMD */
|
||||
|
20
intern/ghost/intern/GHOST_EventOpenHMD.h
Normal file
20
intern/ghost/intern/GHOST_EventOpenHMD.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __GHOST_EVENTOPENHMD_H_
|
||||
#define __GHOST_EVENTOPENHMD_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
class GHOST_EventOpenHMD : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
GHOST_EventOpenHMD(GHOST_TUns64 time, GHOST_TEventOpenHMDSubTypes subtype, GHOST_IWindow *window)
|
||||
: GHOST_Event(time, GHOST_kEventHMD, window)
|
||||
{
|
||||
m_OpenHMDEventData.subtype = subtype;
|
||||
m_data = &m_OpenHMDEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
GHOST_TEventOpenHMDData m_OpenHMDEventData;
|
||||
};
|
||||
|
||||
#endif // __GHOST_EVENTOPENHMD_H_
|
541
intern/ghost/intern/GHOST_OpenHMDManager.cpp
Normal file
541
intern/ghost/intern/GHOST_OpenHMDManager.cpp
Normal file
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "GHOST_OpenHMDManager.h"
|
||||
#include "GHOST_EventOpenHMD.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
|
||||
#include "include/openhmd.h"
|
||||
|
||||
#ifdef WITH_OPENHMD_DYNLOAD
|
||||
# include "udew.h"
|
||||
#endif
|
||||
|
||||
#define CONTEXT_ASSERT GHOST_ASSERT(m_context, "No OpenHMD context found")
|
||||
|
||||
GHOST_OpenHMDManager::GHOST_OpenHMDManager(GHOST_System& sys)
|
||||
: m_system(sys),
|
||||
m_context(NULL),
|
||||
m_device(NULL),
|
||||
m_deviceIndex(-1),
|
||||
m_projection_params(NULL)
|
||||
{
|
||||
// context can be pre-created. the device can be opened later at will
|
||||
createContext();
|
||||
}
|
||||
|
||||
GHOST_OpenHMDManager::~GHOST_OpenHMDManager()
|
||||
{
|
||||
closeDevice();
|
||||
destroyContext();
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::processEvents()
|
||||
{
|
||||
GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
|
||||
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
|
||||
GHOST_TUns64 now = m_system.getMilliSeconds();
|
||||
static int num_devices_prev = 0;
|
||||
const int num_devices = getNumDevices();
|
||||
bool anyProcessed = false;
|
||||
|
||||
/* DeviceNumChanged event
|
||||
* Would be nicer if OpenHMD could handle this for us. */
|
||||
if (num_devices_prev != num_devices) {
|
||||
GHOST_EventOpenHMD *event = new GHOST_EventOpenHMD(now, GHOST_kDeviceNumChanged, window);
|
||||
m_system.pushEvent(event);
|
||||
|
||||
num_devices_prev = num_devices;
|
||||
anyProcessed = true;
|
||||
}
|
||||
/* OrientationUpdate event
|
||||
* We might want to add a timeout check here to avoid too many updates. */
|
||||
if (m_device) {
|
||||
GHOST_EventOpenHMD *event = new GHOST_EventOpenHMD(now, GHOST_kOrientationUpdate, window);
|
||||
GHOST_TEventOpenHMDData *data = (GHOST_TEventOpenHMDData*)event->getData();
|
||||
|
||||
ohmd_ctx_update(m_context);
|
||||
if (!getRotationQuat(data->orientation))
|
||||
return false;
|
||||
|
||||
m_system.pushEvent(event);
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::available() const
|
||||
{
|
||||
return (m_device != NULL);
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::createContext()
|
||||
{
|
||||
if (m_context != NULL)
|
||||
return true;
|
||||
|
||||
#ifdef WITH_OPENHMD_DYNLOAD
|
||||
static bool udew_initialized = false;
|
||||
static bool udew_success = true;
|
||||
if (!udew_initialized) {
|
||||
udew_initialized = true;
|
||||
int result = udewInit();
|
||||
if (result != UDEW_SUCCESS) {
|
||||
udew_success = false;
|
||||
fprintf(stderr, "Failed to open udev library\n");
|
||||
}
|
||||
}
|
||||
if (!udew_success) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (m_context = ohmd_ctx_create());
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::destroyContext()
|
||||
{
|
||||
ohmd_ctx_destroy(m_context);
|
||||
m_context = NULL;
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::openDevice(const char *requested_vendor_name, const char *requested_device_name)
|
||||
{
|
||||
// Create the context if it hasn't been created yet.
|
||||
// Do not check for m_available as that indicates both the context and device
|
||||
// are valid, which isn't the case if the context isn't available.
|
||||
if (!createContext()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
int num_devices = ohmd_ctx_probe(m_context);
|
||||
for (int i = 0; i < num_devices; ++i) {
|
||||
const char* device_name = ohmd_list_gets(m_context, i, OHMD_PRODUCT);
|
||||
const char* vendor_name = ohmd_list_gets(m_context, i, OHMD_VENDOR);
|
||||
|
||||
if (strcmp(device_name, requested_device_name) == 0 && strcmp(vendor_name, requested_vendor_name) == 0) {
|
||||
success = openDevice(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::openDevice(int index)
|
||||
{
|
||||
// Create the context if it hasn't been created yet
|
||||
// Do not check for m_available as that indicates both the context and device
|
||||
// are valid, which isn't the case if the context isn't available.
|
||||
if (!createContext()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// out of bounds
|
||||
if (index >= ohmd_ctx_probe(m_context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Blender only allows one opened device at a time
|
||||
if (getOpenHMDDevice()) {
|
||||
closeDevice();
|
||||
}
|
||||
|
||||
// can't fail to open the device
|
||||
m_deviceIndex = index;
|
||||
|
||||
ohmd_device_settings* settings = ohmd_device_settings_create(m_context);
|
||||
|
||||
// If OHMD_IDS_AUTOMATIC_UPDATE is set to 0, ohmd_ctx_update() must be called at least 10 times per second.
|
||||
// It is enabled by default, runs in seperate thread.
|
||||
// This allows for correct tracking on low framerates, needed for heavy scenes.
|
||||
|
||||
int auto_update = 1;
|
||||
ohmd_device_settings_seti(settings, OHMD_IDS_AUTOMATIC_UPDATE, &auto_update);
|
||||
|
||||
m_device = ohmd_list_open_device_s(m_context, index, settings);
|
||||
ohmd_device_settings_destroy(settings); //cleanup settings
|
||||
|
||||
if (!m_device) {
|
||||
printf("Could not open device, please check your rights\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_projection_params = new OpenHMDDistortionParameters;
|
||||
// Set the thing for the stuff
|
||||
ohmd_device_getf(m_device, OHMD_SCREEN_HORIZONTAL_SIZE, &(m_projection_params->viewport_scale[0]));
|
||||
m_projection_params->viewport_scale[0] /= 2.0f;
|
||||
ohmd_device_getf(m_device, OHMD_SCREEN_VERTICAL_SIZE, &(m_projection_params->viewport_scale[1]));
|
||||
//distortion coefficients
|
||||
ohmd_device_getf(m_device, OHMD_UNIVERSAL_DISTORTION_K, &(m_projection_params->distortion_coeffs[0]));
|
||||
ohmd_device_getf(m_device, OHMD_UNIVERSAL_ABERRATION_K, &(m_projection_params->aberr_scale[0]));
|
||||
//calculate lens centers (assuming the eye separation is the distance betweenteh lense centers)
|
||||
ohmd_device_getf(m_device, OHMD_LENS_HORIZONTAL_SEPARATION, &m_projection_params->sep);
|
||||
ohmd_device_getf(m_device, OHMD_LENS_VERTICAL_POSITION, &(m_projection_params->left_lens_center[1]));
|
||||
ohmd_device_getf(m_device, OHMD_LENS_VERTICAL_POSITION, &(m_projection_params->right_lens_center[1]));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::closeDevice()
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_close_device(m_device);
|
||||
|
||||
delete m_projection_params;
|
||||
m_device = NULL;
|
||||
m_deviceIndex = -1;
|
||||
}
|
||||
|
||||
int GHOST_OpenHMDManager::getNumDevices()
|
||||
{
|
||||
CONTEXT_ASSERT;
|
||||
return ohmd_ctx_probe(m_context);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getError() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ohmd_ctx_get_error(m_context);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getDeviceName() const
|
||||
{
|
||||
if (!m_device)
|
||||
return NULL;
|
||||
|
||||
ohmd_ctx_probe(m_context);
|
||||
return ohmd_list_gets(m_context, m_deviceIndex, OHMD_PRODUCT);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getDeviceName(int index)
|
||||
{
|
||||
CONTEXT_ASSERT;
|
||||
// Probe to fetch the device information from the hardware
|
||||
ohmd_ctx_probe(m_context);
|
||||
return ohmd_list_gets(m_context, index, OHMD_PRODUCT);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getVendorName() const
|
||||
{
|
||||
if (!m_device)
|
||||
return NULL;
|
||||
|
||||
ohmd_ctx_probe(m_context);
|
||||
return ohmd_list_gets(m_context, m_deviceIndex, OHMD_VENDOR);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getVendorName(int index)
|
||||
{
|
||||
CONTEXT_ASSERT;
|
||||
// Probe to fetch the device information from the hardware
|
||||
ohmd_ctx_probe(m_context);
|
||||
return ohmd_list_gets(m_context, index, OHMD_VENDOR);
|
||||
}
|
||||
|
||||
const char *GHOST_OpenHMDManager::getPath() const
|
||||
{
|
||||
if (!m_device)
|
||||
return NULL;
|
||||
|
||||
return ohmd_list_gets(m_context, m_deviceIndex, OHMD_PATH);
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::getRotationQuat(float orientation[4]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float tmp[4];
|
||||
if (ohmd_device_getf(m_device, OHMD_ROTATION_QUAT, tmp) < 0)
|
||||
return false;
|
||||
|
||||
// Convert from x, y, z, w space (OpenHMD) to w, x, y, z (Blender)
|
||||
orientation[0] = tmp[3];
|
||||
orientation[1] = tmp[0];
|
||||
orientation[2] = tmp[1];
|
||||
orientation[3] = tmp[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getLeftEyeGLModelviewMatrix(float mat[4][4]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX, *mat);
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getRightEyeGLModelviewMatrix(float mat[4][4]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX, *mat);
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getLeftEyeGLProjectionMatrix(float mat[4][4]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX, *mat);
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getRightEyeGLProjectionMatrix(float mat[4][4]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX, *mat);
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getPositionVector(float position[3]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_POSITION_VECTOR, position);
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getScreenHorizontalSize() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_SCREEN_HORIZONTAL_SIZE, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getScreenVerticalSize() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_SCREEN_VERTICAL_SIZE, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getLensHorizontalSeparation() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_LENS_HORIZONTAL_SEPARATION, &val);
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getLensVerticalPosition() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_LENS_VERTICAL_POSITION, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getLeftEyeFOV() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_LEFT_EYE_FOV, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getLeftEyeAspectRatio() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_LEFT_EYE_ASPECT_RATIO, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getRightEyeFOV() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_RIGHT_EYE_FOV, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getRightEyeAspectRatio() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_RIGHT_EYE_ASPECT_RATIO, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns -1 if not found.
|
||||
*/
|
||||
float GHOST_OpenHMDManager::getEyeIPD() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_EYE_IPD, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getProjectionZFar() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_PROJECTION_ZFAR, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float GHOST_OpenHMDManager::getProjectionZNear() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float val = -1;
|
||||
ohmd_device_getf(m_device, OHMD_PROJECTION_ZNEAR, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void GHOST_OpenHMDManager::getDistortion(float distortion[6]) const
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
ohmd_device_getf(m_device, OHMD_DISTORTION_K, distortion);
|
||||
}
|
||||
|
||||
int GHOST_OpenHMDManager::getScreenHorizontalResolution() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int val = -1;
|
||||
ohmd_device_geti(m_device, OHMD_SCREEN_HORIZONTAL_RESOLUTION, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
int GHOST_OpenHMDManager::getScreenVerticalResolution() const
|
||||
{
|
||||
if (!m_device) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int val = -1;
|
||||
ohmd_device_geti(m_device, OHMD_SCREEN_VERTICAL_RESOLUTION, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::setEyeIPD(float val)
|
||||
{
|
||||
if (!m_device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ohmd_device_setf(m_device, OHMD_EYE_IPD, &val);
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::setProjectionZFar(float val)
|
||||
{
|
||||
if (!m_device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ohmd_device_setf(m_device, OHMD_PROJECTION_ZFAR, &val);
|
||||
}
|
||||
|
||||
bool GHOST_OpenHMDManager::setProjectionZNear(float val)
|
||||
{
|
||||
if (!m_device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ohmd_device_setf(m_device, OHMD_PROJECTION_ZNEAR, &val);
|
||||
}
|
||||
|
||||
ohmd_context *GHOST_OpenHMDManager::getOpenHMDContext()
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
ohmd_device *GHOST_OpenHMDManager::getOpenHMDDevice()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
const int GHOST_OpenHMDManager::getDeviceIndex()
|
||||
{
|
||||
return m_deviceIndex;
|
||||
}
|
||||
|
||||
void* GHOST_OpenHMDManager::getDistortionParameters()
|
||||
{
|
||||
if (!m_device) {
|
||||
return NULL;
|
||||
}
|
||||
return m_projection_params;
|
||||
}
|
319
intern/ghost/intern/GHOST_OpenHMDManager.h
Normal file
319
intern/ghost/intern/GHOST_OpenHMDManager.h
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __GHOST_OPENHMDMANAGER_H__
|
||||
#define __GHOST_OPENHMDMANAGER_H__
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
struct ohmd_context;
|
||||
struct ohmd_device;
|
||||
|
||||
struct OpenHMDDistortionParameters {
|
||||
float viewport_scale[2];
|
||||
float distortion_coeffs[4];
|
||||
float aberr_scale[3];
|
||||
float sep;
|
||||
float left_lens_center[2];
|
||||
float right_lens_center[2];
|
||||
};
|
||||
|
||||
class GHOST_OpenHMDManager
|
||||
{
|
||||
public:
|
||||
// TODO maybe cut out dependency on the system? (only used for getMilliSeconds and
|
||||
// none of the others without platform implementations use it)
|
||||
GHOST_OpenHMDManager(GHOST_System&);
|
||||
virtual ~GHOST_OpenHMDManager();
|
||||
|
||||
/**
|
||||
* \return True if there is a device opened and ready for polling, false otherwise.
|
||||
*/
|
||||
bool available() const;
|
||||
|
||||
/**
|
||||
* Update the device context and generate an event containing the current orientation of the device.
|
||||
* \return A boolean indicating success.
|
||||
*/
|
||||
bool processEvents();
|
||||
|
||||
/**
|
||||
* Select the device matching the given vendor and device name.
|
||||
* This device will then be the device for which ghost events will be generated.
|
||||
* If no device with the correct name and vendor can be found, or an error occurs,
|
||||
* the current device is preserved.
|
||||
* \param requested_vendor_name The exact name of the vendor for the requested device
|
||||
* \param requested_device_name The exact name of the requested device.
|
||||
* \return A boolean indicating success.
|
||||
*/
|
||||
bool openDevice(const char *requested_vendor_name, const char *requested_device_name);
|
||||
|
||||
/**
|
||||
* Select a device by index
|
||||
* \param index The index of the requested device
|
||||
* See openDevice(const char*, const char*) for more information.
|
||||
*/
|
||||
bool openDevice(int index);
|
||||
|
||||
/**
|
||||
* Close the currently opened device (if available).
|
||||
* This means no more events will be generated until another device is opened using openDevice.
|
||||
* Has no effect is available() is false.
|
||||
*/
|
||||
void closeDevice();
|
||||
|
||||
/**
|
||||
* \return The number of connected devices.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
int getNumDevices();
|
||||
|
||||
///TODO add a function to retrieve a list of connected devices, or the data of a single device by index.
|
||||
//the data should contain at least the device name and vendor name.
|
||||
|
||||
/**
|
||||
* \return A c-style string containing the last error as a human-readable message
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getError() const;
|
||||
|
||||
/**
|
||||
* \return A c-style string with the human-readable name of the current device.
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getDeviceName() const;
|
||||
|
||||
/**
|
||||
* \return A c-style string with the human-readable name of the device at \a index.
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getDeviceName(int index);
|
||||
|
||||
/**
|
||||
* \return A c-style string with the human-readable name of the vendor of the the current device.
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getVendorName() const;
|
||||
|
||||
/**
|
||||
* \return A c-style string with the human-readable name of the vendor at \a index.
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getVendorName(int index);
|
||||
|
||||
/**
|
||||
* \return A c-style string with the driver-specific path where the current device is attached.
|
||||
* NULL is returned if available() is false.
|
||||
*/
|
||||
const char *getPath() const;
|
||||
|
||||
/**
|
||||
* \param orientation The absolute orientation of the device, as quaternion, in blender format (w,x,y,z)
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
bool getRotationQuat(float orientation[4]) const;
|
||||
|
||||
/**
|
||||
* \param mat A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the left eye of the HMD.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getLeftEyeGLModelviewMatrix(float mat[4][4]) const;
|
||||
|
||||
/**
|
||||
* \param mat A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the right eye of the HMD.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getRightEyeGLModelviewMatrix(float mat[4][4]) const;
|
||||
|
||||
/**
|
||||
* \param mat A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the left eye of the HMD.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getLeftEyeGLProjectionMatrix(float mat[4][4]) const;
|
||||
|
||||
/**
|
||||
* \param mat A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the right eye of the HMD.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getRightEyeGLProjectionMatrix(float mat[4][4]) const;
|
||||
|
||||
/**
|
||||
* \param position A 3-D vector representing the absolute position of the device, in space.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getPositionVector(float position[3]) const;
|
||||
|
||||
/**
|
||||
* \return Physical width of the device screen in metres.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getScreenHorizontalSize() const;
|
||||
|
||||
/**
|
||||
* \return Physical height of the device screen in metres.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getScreenVerticalSize() const;
|
||||
|
||||
/**
|
||||
* \return Physical separation of the device lenses in metres.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getLensHorizontalSeparation() const;
|
||||
|
||||
/**
|
||||
* \return Physical vertical position of the lenses in metres.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getLensVerticalPosition() const;
|
||||
|
||||
/**
|
||||
* \return Physical field of view for the left eye in degrees.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getLeftEyeFOV() const;
|
||||
|
||||
/**
|
||||
* \return Physical display aspect ratio for the left eye screen.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getLeftEyeAspectRatio() const;
|
||||
|
||||
/**
|
||||
* \return Physical display aspect ratio for the left eye screen.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getRightEyeFOV() const;
|
||||
|
||||
/**
|
||||
* \return Physical display aspect ratio for the right eye screen.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getRightEyeAspectRatio() const;
|
||||
|
||||
/**
|
||||
* \return Physical interpupillary distance of the user in metres.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getEyeIPD() const;
|
||||
|
||||
/**
|
||||
* \return Z-far value for the projection matrix calculations (i.e. drawing distance).
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getProjectionZFar() const;
|
||||
|
||||
/**
|
||||
* \return Z-near value for the projection matrix calculations (i.e. close clipping distance).
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
float getProjectionZNear() const;
|
||||
|
||||
/**
|
||||
* \param distortion Device specific distortion value.
|
||||
* Nothing is written if available() is false.
|
||||
*/
|
||||
void getDistortion(float distortion[6]) const;
|
||||
|
||||
/**
|
||||
* \return Physical horizontal resolution of the device screen.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
int getScreenHorizontalResolution() const;
|
||||
|
||||
/**
|
||||
* \return Physical vertical resolution of the device screen.
|
||||
* -1 is returned if available() is false.
|
||||
*/
|
||||
int getScreenVerticalResolution() const;
|
||||
|
||||
/**
|
||||
* Sets the physical interpupillary distance of the user in metres.
|
||||
* This function can only succeed if available() is true.
|
||||
* \param val The value to be set.
|
||||
* \return A boolean indicating success.
|
||||
*/
|
||||
bool setEyeIPD(float val);
|
||||
/**
|
||||
|
||||
* Sets the Z-far value for the projection matrix calculations (i.e. drawing distance).
|
||||
* This function can only succeed if available() is true.
|
||||
* \param val The value to be set.
|
||||
* \return A boolean indicating success.
|
||||
*/
|
||||
bool setProjectionZFar(float val);
|
||||
|
||||
/**
|
||||
* Sets the Z-near value for the projection matrix calculations (i.e. close clipping distance).
|
||||
* This function can only succeed if available() is true.
|
||||
* \param val The value to be set.
|
||||
* \return A boolean indicating success.
|
||||
*/
|
||||
bool setProjectionZNear(float val);
|
||||
|
||||
/**
|
||||
* Get the internal OpenHMD context of this manager.
|
||||
* \return The context
|
||||
* Context is only valid if available() is true.
|
||||
*/
|
||||
struct ohmd_context *getOpenHMDContext();
|
||||
|
||||
/**
|
||||
* Get the internal OpenHMD device for the currently selected device of this manager.
|
||||
* \return The device
|
||||
* Device is only valid if available() is true.
|
||||
*/
|
||||
ohmd_device *getOpenHMDDevice();
|
||||
|
||||
/**
|
||||
* Get the index of the currently selected device of this manager.
|
||||
* \return The index.
|
||||
* Index is only valid if available() is true.
|
||||
*/
|
||||
const int getDeviceIndex();
|
||||
|
||||
/**
|
||||
* \return contains all the information for the lens correction shader
|
||||
*/
|
||||
void* getDistortionParameters();
|
||||
|
||||
protected:
|
||||
GHOST_System& m_system;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Create the context if it hasn't been created yet.
|
||||
* The context lives as long as the #GHOST_OpenHMDManager lives.
|
||||
* \return True if a context was created or was already available.
|
||||
*/
|
||||
bool createContext();
|
||||
/**
|
||||
* Destroy and NULL #m_context. Should only be done when deleting #GHOST_OpenHMDManager.
|
||||
*/
|
||||
void destroyContext();
|
||||
|
||||
ohmd_context *m_context;
|
||||
ohmd_device *m_device;
|
||||
int m_deviceIndex;
|
||||
OpenHMDDistortionParameters *m_projection_params;
|
||||
};
|
||||
|
||||
#endif //__GHOST_OPENHMDMANAGER_H__
|
@@ -41,6 +41,7 @@
|
||||
#include "GHOST_TimerTask.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_OpenHMDManager.h"
|
||||
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
# include "GHOST_NDOFManager.h"
|
||||
@@ -51,10 +52,11 @@ GHOST_System::GHOST_System()
|
||||
m_displayManager(NULL),
|
||||
m_timerManager(NULL),
|
||||
m_windowManager(NULL),
|
||||
m_eventManager(NULL)
|
||||
m_eventManager(NULL),
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
, m_ndofManager(0)
|
||||
m_ndofManager(0),
|
||||
#endif
|
||||
m_openHMDManager(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -215,6 +217,19 @@ bool GHOST_System::getFullScreen(void)
|
||||
return fullScreen;
|
||||
}
|
||||
|
||||
bool GHOST_System::processEvents(bool waitForEvent)
|
||||
{
|
||||
bool anyProcessed = false;
|
||||
#ifdef WITH_OPENHMD
|
||||
if (m_openHMDManager->processEvents()) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)waitForEvent; // quiet warning!
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
void GHOST_System::dispatchEvents()
|
||||
{
|
||||
@@ -306,7 +321,10 @@ GHOST_TSuccess GHOST_System::init()
|
||||
m_timerManager = new GHOST_TimerManager();
|
||||
m_windowManager = new GHOST_WindowManager();
|
||||
m_eventManager = new GHOST_EventManager();
|
||||
|
||||
#ifdef WITH_OPENHMD
|
||||
m_openHMDManager = new GHOST_OpenHMDManager(*this);
|
||||
#endif
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
if (m_eventManager) {
|
||||
m_eventPrinter = new GHOST_EventPrinter();
|
||||
@@ -345,6 +363,10 @@ GHOST_TSuccess GHOST_System::exit()
|
||||
delete m_ndofManager;
|
||||
m_ndofManager = NULL;
|
||||
#endif
|
||||
if (m_openHMDManager) {
|
||||
delete m_openHMDManager;
|
||||
m_openHMDManager = NULL;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
@@ -51,6 +51,7 @@ class GHOST_WindowManager;
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
class GHOST_NDOFManager;
|
||||
#endif
|
||||
class GHOST_OpenHMDManager;
|
||||
|
||||
/**
|
||||
* Implementation of platform independent functionality of the GHOST_ISystem
|
||||
@@ -182,12 +183,9 @@ public:
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Inherited from GHOST_ISystem but left pure virtual
|
||||
*
|
||||
* virtual bool processEvents(bool waitForEvent) = 0;
|
||||
* Implemented for operating system independent event handling
|
||||
*/
|
||||
|
||||
|
||||
bool processEvents(bool waitForEvent);
|
||||
|
||||
/**
|
||||
* Dispatches all the events on the stack.
|
||||
@@ -284,6 +282,11 @@ public:
|
||||
inline GHOST_NDOFManager *getNDOFManager() const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \return A pointer to our OpenHMD manager.
|
||||
*/
|
||||
virtual GHOST_OpenHMDManager *getOpenHMDManager() const;
|
||||
|
||||
/**
|
||||
* Returns the state of all modifier keys.
|
||||
* \param keys The state of all modifier keys (true == pressed).
|
||||
@@ -358,7 +361,9 @@ protected:
|
||||
/** The N-degree of freedom device manager */
|
||||
GHOST_NDOFManager *m_ndofManager;
|
||||
#endif
|
||||
|
||||
|
||||
GHOST_OpenHMDManager *m_openHMDManager;
|
||||
|
||||
/** Prints all the events. */
|
||||
#ifdef GHOST_DEBUG
|
||||
GHOST_EventPrinter *m_eventPrinter;
|
||||
@@ -391,5 +396,10 @@ inline GHOST_NDOFManager *GHOST_System::getNDOFManager() const
|
||||
}
|
||||
#endif
|
||||
|
||||
inline GHOST_OpenHMDManager *GHOST_System::getOpenHMDManager() const
|
||||
{
|
||||
return m_openHMDManager;
|
||||
}
|
||||
|
||||
#endif // __GHOST_SYSTEM_H__
|
||||
|
||||
|
@@ -746,6 +746,11 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
|
||||
/* Call base class to update os independent events */
|
||||
if (GHOST_System::processEvents(anyProcessed)) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (event != nil);
|
||||
#if 0
|
||||
} while (waitForEvent && !anyProcessed); // Needed only for timer implementation
|
||||
|
@@ -596,6 +596,11 @@ GHOST_SystemSDL::processEvents(bool waitForEvent)
|
||||
if (generateWindowExposeEvents()) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
/* Call base class to update os independent events */
|
||||
if (GHOST_System::processEvents(anyProcessed)) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
|
@@ -337,6 +337,11 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
|
||||
::DispatchMessageW(&msg);
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
/* Call base class to update os independent events */
|
||||
if (GHOST_System::processEvents(anyProcessed)) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
|
@@ -631,7 +631,10 @@ processEvents(
|
||||
anyProcessed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call base class to update os independent events */
|
||||
if (GHOST_System::processEvents(anyProcessed)) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
|
@@ -151,10 +151,11 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
|
||||
st = context.camera.stereo
|
||||
cam = context.camera
|
||||
|
||||
col = layout.column()
|
||||
|
||||
is_spherical_stereo = cam.type != 'ORTHO' and render.use_spherical_stereo
|
||||
use_spherical_stereo = is_spherical_stereo and st.use_spherical_stereo
|
||||
|
||||
col = layout.column()
|
||||
col.row().prop(st, "convergence_mode", expand=True)
|
||||
|
||||
sub = col.column()
|
||||
|
@@ -199,22 +199,22 @@ class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel):
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
rv = rd.views.active
|
||||
wm = context.window_manager
|
||||
|
||||
layout.active = rd.use_multiview
|
||||
layout.enabled = rd.use_multiview
|
||||
basic_stereo = rd.views_format == 'STEREO_3D'
|
||||
|
||||
row = layout.row()
|
||||
row.prop(rd, "views_format", expand=True)
|
||||
|
||||
if basic_stereo:
|
||||
if rd.views_format == 'STEREO_3D':
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="File Suffix:")
|
||||
row.prop(rv, "file_suffix", text="")
|
||||
|
||||
else:
|
||||
elif rd.views_format == 'MULTIVIEW':
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
|
||||
|
||||
|
@@ -292,6 +292,7 @@ class INFO_MT_window(Menu):
|
||||
import sys
|
||||
|
||||
layout = self.layout
|
||||
rd = context.scene.render
|
||||
|
||||
layout.operator("wm.window_duplicate")
|
||||
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
|
||||
@@ -305,7 +306,7 @@ class INFO_MT_window(Menu):
|
||||
layout.separator()
|
||||
layout.operator("wm.console_toggle", icon='CONSOLE')
|
||||
|
||||
if context.scene.render.use_multiview:
|
||||
if rd.use_multiview and rd.views_format in {'STEREO_3D', 'MULTIVIEW'}:
|
||||
layout.separator()
|
||||
layout.operator("wm.set_stereo_3d", icon='CAMERA_STEREO')
|
||||
|
||||
|
@@ -502,6 +502,17 @@ class USERPREF_PT_system(Panel):
|
||||
col.label(text="OpenSubdiv compute:")
|
||||
col.row().prop(system, "opensubdiv_compute_type", text="")
|
||||
|
||||
if bpy.app.build_options.input_hmd:
|
||||
col.separator()
|
||||
|
||||
col.label(text="Head Mounted Displays:")
|
||||
col.prop(system, "hmd_device", text="Device")
|
||||
col.prop(system, "use_hmd_device_rotation")
|
||||
col.prop(system, "use_hmd_device_ipd")
|
||||
subcol = col.column()
|
||||
subcol.active = (not system.use_hmd_device_ipd) or (system.hmd_device == 'NONE')
|
||||
subcol.prop(system, "hmd_custom_ipd")
|
||||
|
||||
# 2. Column
|
||||
column = split.column()
|
||||
colsplit = column.split(percentage=0.85)
|
||||
|
@@ -3407,6 +3407,37 @@ class VIEW3D_PT_view3d_shading(Panel):
|
||||
subcol.prop(ssao_settings, "samples")
|
||||
subcol.prop(ssao_settings, "color")
|
||||
|
||||
class VIEW3D_PT_view3d_hmd_view(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "HMD View"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bpy.app.build_options.input_hmd
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
wm = context.window_manager
|
||||
view = context.space_data
|
||||
|
||||
session_running = wm.is_hmd_session_running
|
||||
text_win = "Close HMD Window" if wm.has_hmd_window else "Open HMD Window"
|
||||
text_run = "Stop Session" if session_running else "Start Session"
|
||||
icon_run = 'PAUSE' if session_running else 'PLAY'
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("wm.hmd_view_toggle", text=text_win)
|
||||
row.operator("wm.hmd_session_run", text=text_run, icon=icon_run)
|
||||
layout.prop(view, "use_hmd_mirror")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop(wm, "hmd_view_shade", text="Shading")
|
||||
layout.prop(wm, "hmd_view_show_only_render")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_motion_tracking(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@@ -3928,6 +3959,7 @@ classes = (
|
||||
VIEW3D_PT_view3d_display,
|
||||
VIEW3D_PT_view3d_stereo,
|
||||
VIEW3D_PT_view3d_shading,
|
||||
VIEW3D_PT_view3d_hmd_view,
|
||||
VIEW3D_PT_view3d_motion_tracking,
|
||||
VIEW3D_PT_view3d_meshdisplay,
|
||||
VIEW3D_PT_view3d_meshstatvis,
|
||||
|
@@ -140,7 +140,9 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set
|
||||
/* Camera multi-view API */
|
||||
|
||||
struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname);
|
||||
void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]);
|
||||
void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, const float interocular_distance_override, float r_viewmat[4][4]);
|
||||
void BKE_camera_multiview_proj_matrix(const bool is_left, float r_projmat[4][4]);
|
||||
void BKE_camera_multiview_model_matrix_ex(struct RenderData *rd, struct Object *camera, const char *viewname, const float interocular_distance_override, float r_modelmat[4][4]);
|
||||
void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]);
|
||||
float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname);
|
||||
void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname);
|
||||
|
@@ -117,6 +117,8 @@ void BKE_object_obdata_size_init(struct Object *ob, const float scale);
|
||||
void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]);
|
||||
void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3], bool use_drot);
|
||||
void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], bool use_compat);
|
||||
void BKE_object_rot_to_quat(struct Object *ob, float r_quat[4]);
|
||||
void BKE_object_quat_to_rot(struct Object *ob, float quat[4]);
|
||||
void BKE_object_to_mat3(struct Object *ob, float mat[3][3]);
|
||||
void BKE_object_to_mat4(struct Object *ob, float mat[4][4]);
|
||||
void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const bool use_compat, const bool use_parent);
|
||||
|
@@ -285,7 +285,7 @@ struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
|
||||
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
|
||||
void BKE_screen_area_free(struct ScrArea *sa);
|
||||
|
||||
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
|
||||
struct ARegion *BKE_area_find_region_type(const struct ScrArea *sa, int type);
|
||||
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
|
||||
struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
|
||||
struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
|
||||
|
@@ -378,6 +378,10 @@ if(WITH_IMAGE_HDR)
|
||||
add_definitions(-DWITH_HDR)
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
|
||||
if(WITH_CODEC_AVI)
|
||||
list(APPEND INC
|
||||
../avi
|
||||
|
@@ -676,20 +676,20 @@ static void camera_model_matrix(Object *camera, float r_modelmat[4][4])
|
||||
copy_m4_m4(r_modelmat, camera->obmat);
|
||||
}
|
||||
|
||||
static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4])
|
||||
static void camera_stereo3d_model_matrix(
|
||||
Object *camera, const bool is_left, const float interocular_distance_override,
|
||||
float r_modelmat[4][4])
|
||||
{
|
||||
Camera *data = (Camera *)camera->data;
|
||||
float interocular_distance, convergence_distance;
|
||||
short convergence_mode, pivot;
|
||||
float sizemat[4][4];
|
||||
|
||||
float fac = 1.0f;
|
||||
float fac_signed;
|
||||
|
||||
interocular_distance = data->stereo.interocular_distance;
|
||||
convergence_distance = data->stereo.convergence_distance;
|
||||
convergence_mode = data->stereo.convergence_mode;
|
||||
pivot = data->stereo.pivot;
|
||||
const float interocular_distance = interocular_distance_override == -1.0f ?
|
||||
data->stereo.interocular_distance : interocular_distance_override;
|
||||
const short convergence_mode = data->stereo.convergence_mode;
|
||||
const short pivot = data->stereo.pivot;
|
||||
|
||||
if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
|
||||
((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
|
||||
@@ -710,6 +710,7 @@ static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, flo
|
||||
|
||||
/* rotation */
|
||||
if (convergence_mode == CAM_S3D_TOE) {
|
||||
const float convergence_distance = data->stereo.convergence_distance;
|
||||
float angle;
|
||||
float angle_sin, angle_cos;
|
||||
float toeinmat[4][4];
|
||||
@@ -774,9 +775,13 @@ static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, flo
|
||||
}
|
||||
|
||||
/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
|
||||
void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4])
|
||||
void BKE_camera_multiview_view_matrix(
|
||||
RenderData *rd, Object *camera, const bool is_left, const float interocular_distance_override,
|
||||
float r_viewmat[4][4])
|
||||
{
|
||||
BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat);
|
||||
BKE_camera_multiview_model_matrix_ex(
|
||||
rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME,
|
||||
interocular_distance_override, r_viewmat);
|
||||
invert_m4(r_viewmat);
|
||||
}
|
||||
|
||||
@@ -789,7 +794,9 @@ static bool camera_is_left(const char *viewname)
|
||||
return true;
|
||||
}
|
||||
|
||||
void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4])
|
||||
void BKE_camera_multiview_model_matrix_ex(
|
||||
RenderData *rd, Object *camera, const char *viewname, const float interocular_distance_override,
|
||||
float r_modelmat[4][4])
|
||||
{
|
||||
const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
@@ -801,11 +808,16 @@ void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const cha
|
||||
}
|
||||
else { /* SCE_VIEWS_SETUP_BASIC */
|
||||
const bool is_left = camera_is_left(viewname);
|
||||
camera_stereo3d_model_matrix(camera, is_left, r_modelmat);
|
||||
camera_stereo3d_model_matrix(camera, is_left, interocular_distance_override, r_modelmat);
|
||||
}
|
||||
normalize_m4(r_modelmat);
|
||||
}
|
||||
|
||||
void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4])
|
||||
{
|
||||
BKE_camera_multiview_model_matrix_ex(rd, camera, viewname, -1.0f, r_modelmat);
|
||||
}
|
||||
|
||||
bool BKE_camera_multiview_spherical_stereo(RenderData *rd, Object *camera)
|
||||
{
|
||||
Camera *cam;
|
||||
|
@@ -1547,6 +1547,32 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_rot_to_quat(Object *ob, float r_quat[4])
|
||||
{
|
||||
if (ob->rotmode == ROT_MODE_QUAT) {
|
||||
copy_qt_qt(r_quat, ob->quat);
|
||||
}
|
||||
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
|
||||
axis_angle_to_quat(r_quat, ob->rotAxis, ob->rotAngle);
|
||||
}
|
||||
else {
|
||||
eulO_to_quat(r_quat, ob->rot, ob->rotmode);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_quat_to_rot(Object *ob, float quat[4])
|
||||
{
|
||||
if (ob->rotmode == ROT_MODE_QUAT) {
|
||||
copy_qt_qt(ob->quat, quat);
|
||||
}
|
||||
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
|
||||
quat_to_axis_angle(ob->rotAxis, &ob->rotAngle, quat);
|
||||
}
|
||||
else {
|
||||
quat_to_eulO(ob->rot, ob->rotmode, quat);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_tfm_protected_backup(const Object *ob,
|
||||
ObjectTfmProtectedChannels *obtfm)
|
||||
{
|
||||
|
@@ -404,7 +404,7 @@ unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene)
|
||||
/* ***************** Utilities ********************** */
|
||||
|
||||
/* Find a region of the specified type from the given area */
|
||||
ARegion *BKE_area_find_region_type(ScrArea *sa, int type)
|
||||
ARegion *BKE_area_find_region_type(const ScrArea *sa, int type)
|
||||
{
|
||||
if (sa) {
|
||||
ARegion *ar;
|
||||
@@ -682,4 +682,10 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
|
||||
|
||||
GPU_fx_compositor_init_ssao_settings(fx_ssao);
|
||||
}
|
||||
|
||||
if ((fx_settings->lensdist == NULL) &&
|
||||
(fx_settings->fx_flag & GPU_FX_FLAG_LensDist))
|
||||
{
|
||||
fx_settings->lensdist = MEM_callocN(sizeof(GPULensDistSettings), __func__);
|
||||
}
|
||||
}
|
||||
|
@@ -90,6 +90,10 @@ if(WITH_ALEMBIC)
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}")
|
||||
|
||||
# needed so writefile.c can use dna_type_offsets.h
|
||||
|
@@ -6213,7 +6213,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
|
||||
|
||||
id_us_ensure_real(&wm->id);
|
||||
link_list(fd, &wm->windows);
|
||||
|
||||
#ifdef WITH_INPUT_HMD
|
||||
wm->hmd_view.hmd_win = newdataadr(fd, wm->hmd_view.hmd_win);
|
||||
#else
|
||||
wm->hmd_view.hmd_win = NULL;
|
||||
#endif
|
||||
|
||||
for (win = wm->windows.first; win; win = win->next) {
|
||||
win->ghostwin = NULL;
|
||||
win->eventstate = NULL;
|
||||
@@ -7176,7 +7181,9 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
|
||||
v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
|
||||
if (v3d->fx_settings.ssao)
|
||||
v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
|
||||
|
||||
if (v3d->fx_settings.lensdist)
|
||||
v3d->fx_settings.lensdist = newdataadr(fd, v3d->fx_settings.lensdist);
|
||||
|
||||
blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
|
||||
}
|
||||
else if (sl->spacetype == SPACE_IPO) {
|
||||
|
@@ -1559,6 +1559,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "wmWindowManager", "HMDViewInfo", "hmd_view")) {
|
||||
for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) {
|
||||
wm->hmd_view.view_shade = OB_SOLID;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* To be added to next subversion bump! */
|
||||
{
|
||||
/* Mask primitive adding code was not initializing correctly id_type of its points' parent. */
|
||||
|
@@ -2933,6 +2933,9 @@ static void write_screen(WriteData *wd, bScreen *sc)
|
||||
if (v3d->fx_settings.dof) {
|
||||
writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
|
||||
}
|
||||
if (v3d->fx_settings.lensdist) {
|
||||
writestruct(wd, DATA, GPULensDistSettings, 1, v3d->fx_settings.lensdist);
|
||||
}
|
||||
}
|
||||
else if (sl->spacetype == SPACE_IPO) {
|
||||
SpaceIpo *sipo = (SpaceIpo *)sl;
|
||||
|
@@ -1162,12 +1162,15 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
|
||||
(v3d->drawtype > OB_WIRE))
|
||||
{
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
|
||||
view3d_get_transformation(cdd->vc.ar, cdd->vc.rv3d, NULL, &cdd->mats);
|
||||
|
||||
/* needed or else the draw matrix can be incorrect */
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
ED_view3d_autodist_init(cdd->vc.scene, cdd->vc.ar, cdd->vc.v3d, 0);
|
||||
ED_view3d_autodist_init(cdd->vc.scene, wm, win, cdd->vc.ar, cdd->vc.v3d, 0);
|
||||
|
||||
if (cdd->vc.rv3d->depths) {
|
||||
cdd->vc.rv3d->depths->damaged = true;
|
||||
|
@@ -2010,8 +2010,11 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* init autodist for geometry projection */
|
||||
if (mode == GP_REPROJECT_SURFACE) {
|
||||
view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
|
||||
ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0);
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
|
||||
view3d_region_operator_needs_opengl(win, gsc.ar);
|
||||
ED_view3d_autodist_init(scene, wm, win, gsc.ar, CTX_wm_view3d(C), 0);
|
||||
}
|
||||
|
||||
// TODO: For deforming geometry workflow, create new frames?
|
||||
|
@@ -113,7 +113,8 @@ typedef enum eGPencil_PaintFlags {
|
||||
*/
|
||||
typedef struct tGPsdata {
|
||||
Scene *scene; /* current scene from context */
|
||||
|
||||
|
||||
wmWindowManager *wm; /* window-manager where painting originated */
|
||||
wmWindow *win; /* window where painting originated */
|
||||
ScrArea *sa; /* area where painting originated */
|
||||
ARegion *ar; /* region where painting originated */
|
||||
@@ -637,7 +638,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
|
||||
View3D *v3d = p->sa->spacedata.first;
|
||||
|
||||
view3d_region_operator_needs_opengl(p->win, p->ar);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
ED_view3d_autodist_init(p->scene, p->wm, p->win, p->ar, v3d,
|
||||
(ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* convert screen-coordinates to appropriate coordinates (and store them) */
|
||||
@@ -1239,7 +1241,7 @@ static void gp_stroke_doeraser(tGPsdata *p)
|
||||
View3D *v3d = p->sa->spacedata.first;
|
||||
|
||||
view3d_region_operator_needs_opengl(p->win, p->ar);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
|
||||
ED_view3d_autodist_init(p->scene, p->wm, p->win, p->ar, v3d, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,8 +1393,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pass on current scene and window */
|
||||
/* pass on context info */
|
||||
p->scene = CTX_data_scene(C);
|
||||
p->wm = CTX_wm_manager(C);
|
||||
p->win = CTX_wm_window(C);
|
||||
|
||||
unit_m4(p->imat);
|
||||
@@ -1804,7 +1807,8 @@ static void gp_paint_strokeend(tGPsdata *p)
|
||||
|
||||
/* need to restore the original projection settings before packing up */
|
||||
view3d_region_operator_needs_opengl(p->win, p->ar);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
ED_view3d_autodist_init(p->scene, p->wm, p->win, p->ar, v3d,
|
||||
(ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* check if doing eraser or not */
|
||||
|
@@ -519,6 +519,7 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
|
||||
|
||||
/* init region-specific stuff */
|
||||
if (sa->spacetype == SPACE_VIEW3D) {
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
View3D *v3d = (View3D *)CTX_wm_space_data(C);
|
||||
@@ -528,7 +529,7 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
view3d_region_operator_needs_opengl(win, ar);
|
||||
ED_view3d_autodist_init(scene, ar, v3d, 0);
|
||||
ED_view3d_autodist_init(scene, wm, win, ar, v3d, 0);
|
||||
|
||||
/* for camera view set the subrect */
|
||||
if (rv3d->persp == RV3D_CAMOB) {
|
||||
|
@@ -118,6 +118,7 @@ void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
|
||||
struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
|
||||
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
|
||||
bool ED_screen_stereo3d_required(struct bScreen *screen);
|
||||
bool ED_screen_is_editable(const struct bScreen *screen);
|
||||
|
||||
/* anim */
|
||||
void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
|
||||
|
@@ -289,12 +289,17 @@ int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float
|
||||
unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
|
||||
|
||||
bool ED_view3d_autodist(
|
||||
struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
|
||||
struct Scene *scene,
|
||||
const struct wmWindowManager *wm, const struct wmWindow *win,
|
||||
struct ARegion *ar, struct View3D *v3d,
|
||||
const int mval[2], float mouse_worldloc[3],
|
||||
const bool alphaoverride, const float fallback_depth_pt[3]);
|
||||
|
||||
/* only draw so ED_view3d_autodist_simple can be called many times after */
|
||||
void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
|
||||
void ED_view3d_autodist_init(
|
||||
struct Scene *scene,
|
||||
const struct wmWindowManager *wm, const struct wmWindow *win,
|
||||
struct ARegion *ar, struct View3D *v3d, int mode);
|
||||
bool ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth);
|
||||
bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth);
|
||||
bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
|
||||
@@ -371,11 +376,16 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
|
||||
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
|
||||
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
|
||||
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]);
|
||||
void ED_view3d_setup_interaction(
|
||||
const struct wmWindowManager *wm, const struct wmWindow *win,
|
||||
struct ARegion *region, struct View3D *v3d, struct RegionView3D *rv3d,
|
||||
struct Scene *scene, const rcti *viewplane_rect);
|
||||
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
|
||||
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
|
||||
char ED_view3d_lock_view_from_index(int index);
|
||||
char ED_view3d_axis_view_opposite(char view);
|
||||
bool ED_view3d_lock(struct RegionView3D *rv3d);
|
||||
void ED_view3d_copy_region_view_data(const struct RegionView3D *src, struct RegionView3D *dst);
|
||||
|
||||
uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d);
|
||||
uint64_t ED_view3d_screen_datamask(const struct bScreen *screen);
|
||||
|
@@ -79,6 +79,10 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
|
||||
blender_add_lib(bf_editor_interface "${SRC}" "${INC}" "${INC_SYS}")
|
||||
|
@@ -915,7 +915,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
|
||||
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
|
||||
if (ED_view3d_autodist(scene, CTX_wm_manager(C), win, ar, v3d, mval, co, true, NULL)) {
|
||||
const float mval_center_fl[2] = {
|
||||
(float)ar->winx / 2,
|
||||
(float)ar->winy / 2};
|
||||
|
@@ -56,6 +56,8 @@
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "interface_intern.h"
|
||||
|
||||
/* global for themes */
|
||||
@@ -2764,7 +2766,17 @@ void init_userdef_do_versions(void)
|
||||
* (keep this block even if it becomes empty).
|
||||
*/
|
||||
{
|
||||
|
||||
#ifdef WITH_INPUT_HMD
|
||||
if (WM_HMD_num_devices_get() > 0) {
|
||||
U.hmd_settings.device = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
U.hmd_settings.device = -1;
|
||||
}
|
||||
U.hmd_settings.flag = (USER_HMD_USE_DEVICE_IPD | USER_HMD_USE_DEVICE_ROT);
|
||||
U.hmd_settings.custom_ipd = 0.061f;
|
||||
}
|
||||
|
||||
if (U.pixelsize == 0.0f)
|
||||
|
@@ -678,7 +678,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
* running notifiers again will overwrite */
|
||||
oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal;
|
||||
|
||||
if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) {
|
||||
if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO | GPU_FX_FLAG_LensDist)) {
|
||||
oglrender->fx = GPU_fx_compositor_create();
|
||||
}
|
||||
}
|
||||
|
@@ -54,9 +54,8 @@
|
||||
/* returns biggest area that is not uv/image editor. Note that it uses buttons */
|
||||
/* window as the last possible alternative. */
|
||||
/* would use BKE_screen_find_big_area(...) but this is too specific */
|
||||
static ScrArea *biggest_non_image_area(bContext *C)
|
||||
static ScrArea *biggest_non_image_area(const bScreen *sc)
|
||||
{
|
||||
bScreen *sc = CTX_wm_screen(C);
|
||||
ScrArea *sa, *big = NULL;
|
||||
int size, maxsize = 0, bwmaxsize = 0;
|
||||
short foundwin = 0;
|
||||
@@ -181,7 +180,9 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
|
||||
}
|
||||
|
||||
if (!sa) {
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
sa = find_area_showing_r_result(C, scene, &win);
|
||||
|
||||
if (sa == NULL)
|
||||
sa = find_area_image_empty(C);
|
||||
|
||||
@@ -189,9 +190,9 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
|
||||
if (win && win != CTX_wm_window(C))
|
||||
wm_window_raise(win);
|
||||
|
||||
if (sa == NULL) {
|
||||
if (sa == NULL && ED_screen_is_editable(screen)) {
|
||||
/* find largest open non-image area */
|
||||
sa = biggest_non_image_area(C);
|
||||
sa = biggest_non_image_area(screen);
|
||||
if (sa) {
|
||||
ED_area_newspace(C, sa, SPACE_IMAGE, true);
|
||||
sima = sa->spacedata.first;
|
||||
@@ -206,7 +207,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
|
||||
}
|
||||
else {
|
||||
/* use any area of decent size */
|
||||
sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
|
||||
sa = BKE_screen_find_big_area(screen, SPACE_TYPE_ANY, 0);
|
||||
if (sa->spacetype != SPACE_IMAGE) {
|
||||
// XXX newspace(sa, SPACE_IMAGE);
|
||||
sima = sa->spacedata.first;
|
||||
@@ -216,6 +217,11 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!sa) {
|
||||
/* Could also search in other screens. */
|
||||
BKE_report(reports, RPT_ERROR, "Can't show render result in current screen.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
sima = sa->spacedata.first;
|
||||
|
||||
@@ -255,7 +261,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
}
|
||||
|
||||
/* test if we have a temp screen in front */
|
||||
if (win->screen->temp) {
|
||||
if (win->screen->type == SCREEN_TYPE_TEMP) {
|
||||
wm_window_lower(win);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -301,7 +307,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
|
||||
wmWindow *wincur = CTX_wm_window(C);
|
||||
|
||||
/* test if we have currently a temp screen active */
|
||||
if (wincur->screen->temp) {
|
||||
if (wincur->screen->type == SCREEN_TYPE_TEMP) {
|
||||
wm_window_lower(wincur);
|
||||
}
|
||||
else {
|
||||
@@ -311,7 +317,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
|
||||
/* is there another window on current scene showing result? */
|
||||
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
|
||||
bScreen *sc = win->screen;
|
||||
if ((sc->temp && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
|
||||
if (((sc->type == SCREEN_TYPE_TEMP) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
|
||||
(win == winshow && winshow != wincur))
|
||||
{
|
||||
wm_window_raise(win);
|
||||
|
@@ -49,6 +49,10 @@ set(SRC
|
||||
screen_intern.h
|
||||
)
|
||||
|
||||
if(WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
add_definitions(-DWITH_INTERNATIONAL)
|
||||
endif()
|
||||
|
@@ -473,6 +473,42 @@ void ED_region_set(const bContext *C, ARegion *ar)
|
||||
ED_region_pixelspace(ar);
|
||||
}
|
||||
|
||||
static void region_draw_view_setup(wmWindow *win, ARegion *ar)
|
||||
{
|
||||
#ifdef WITH_INPUT_HMD
|
||||
if (ar->regiontype == RGN_TYPE_TEMPORARY) {
|
||||
/* pass */
|
||||
}
|
||||
else if (!WM_window_is_running_hmd_view(win)) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
ar->winx /= 2;
|
||||
ar->winrct.xmax -= ar->winx;
|
||||
wm_subwindow_rect_set(win, ar->swinid, &ar->winrct);
|
||||
}
|
||||
#else
|
||||
UNUSED_VARS(win, ar);
|
||||
#endif
|
||||
}
|
||||
static void region_draw_view_reset(wmWindow *win, ARegion *ar)
|
||||
{
|
||||
#ifdef WITH_INPUT_HMD
|
||||
if (ar->regiontype == RGN_TYPE_TEMPORARY) {
|
||||
/* pass */
|
||||
}
|
||||
else if (!WM_window_is_running_hmd_view(win)) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
ar->winrct.xmax += ar->winx;
|
||||
ar->winx *= 2;
|
||||
wm_subwindow_rect_set(win, ar->swinid, &ar->winrct);
|
||||
}
|
||||
#else
|
||||
UNUSED_VARS(win, ar);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* only exported for WM */
|
||||
void ED_region_do_draw(bContext *C, ARegion *ar)
|
||||
@@ -486,6 +522,8 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
|
||||
if (at->do_lock)
|
||||
return;
|
||||
|
||||
region_draw_view_setup(win, ar);
|
||||
|
||||
/* if no partial draw rect set, full rect */
|
||||
if (ar->drawrct.xmin == ar->drawrct.xmax) {
|
||||
ar->drawrct = ar->winrct;
|
||||
@@ -545,6 +583,8 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
|
||||
region_draw_emboss(ar, &ar->winrct);
|
||||
}
|
||||
}
|
||||
|
||||
region_draw_view_reset(win, ar);
|
||||
}
|
||||
|
||||
/* **********************************
|
||||
@@ -1529,7 +1569,11 @@ void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar)
|
||||
void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
|
||||
|
||||
if (!ED_screen_is_editable(CTX_wm_screen(C))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ar->flag ^= RGN_FLAG_HIDDEN;
|
||||
|
||||
if (do_fade && ar->overlap) {
|
||||
|
@@ -1344,7 +1344,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
|
||||
/* mark it available for use for other windows */
|
||||
screen->winid = 0;
|
||||
|
||||
if (prevwin->screen->temp == 0) {
|
||||
if (prevwin->screen->type == SCREEN_TYPE_NORMAL) {
|
||||
/* use previous window if possible */
|
||||
CTX_wm_window_set(C, prevwin);
|
||||
}
|
||||
@@ -1495,7 +1495,8 @@ bool ED_screen_set(bContext *C, bScreen *sc)
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
bScreen *oldscreen = CTX_wm_screen(C);
|
||||
|
||||
|
||||
BLI_assert(ED_screen_is_editable(sc)); /* Caller should check */
|
||||
/* validate screen, it's called with notifier reference */
|
||||
if (BLI_findindex(&bmain->screen, sc) == -1) {
|
||||
return true;
|
||||
@@ -1623,12 +1624,12 @@ bool ED_screen_delete(bContext *C, bScreen *sc)
|
||||
* can safely assume ours is not in use anywhere an delete it */
|
||||
|
||||
for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
|
||||
if (!ed_screen_used(wm, newsc) && !newsc->temp)
|
||||
if (!ed_screen_used(wm, newsc) && newsc->type != SCREEN_TYPE_TEMP)
|
||||
break;
|
||||
|
||||
if (!newsc) {
|
||||
for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
|
||||
if (!ed_screen_used(wm, newsc) && !newsc->temp)
|
||||
if (!ed_screen_used(wm, newsc) && newsc->type != SCREEN_TYPE_TEMP)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1943,7 +1944,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
|
||||
sc = ED_screen_add(win, oldscreen->scene, newname);
|
||||
sc->state = state;
|
||||
sc->redraws_flag = oldscreen->redraws_flag;
|
||||
sc->temp = oldscreen->temp;
|
||||
sc->type = oldscreen->type;
|
||||
|
||||
/* timer */
|
||||
sc->animtimer = oldscreen->animtimer;
|
||||
@@ -2256,3 +2257,8 @@ bool ED_screen_stereo3d_required(bScreen *screen)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ED_screen_is_editable(const bScreen *screen)
|
||||
{
|
||||
return (screen && screen->type != SCREEN_TYPE_RESTRICTED);
|
||||
}
|
||||
|
@@ -2385,7 +2385,7 @@ static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev)
|
||||
return ((screen->winid == 0) &&
|
||||
/* in typical usage these should have a nonzero winid
|
||||
* (all temp screens should be used, or closed & freed). */
|
||||
(screen->temp == false) &&
|
||||
(screen->type == SCREEN_TYPE_NORMAL) &&
|
||||
(screen->state == SCREENNORMAL) &&
|
||||
(screen != screen_prev) &&
|
||||
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
|
||||
@@ -2403,7 +2403,7 @@ static int screen_set_exec(bContext *C, wmOperator *op)
|
||||
int delta = RNA_int_get(op->ptr, "delta");
|
||||
|
||||
/* temp screens are for userpref or render display */
|
||||
if (screen->temp || (sa && sa->full && sa->full->temp)) {
|
||||
if (screen->type != SCREEN_TYPE_NORMAL || (sa && sa->full && sa->full->type != SCREEN_TYPE_NORMAL)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
@@ -2456,6 +2456,10 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot)
|
||||
|
||||
/* ************** screen full-area operator ***************************** */
|
||||
|
||||
static int screen_maximize_area_poll(bContext *C)
|
||||
{
|
||||
return ED_operator_areaactive(C) && ED_screen_is_editable(CTX_wm_screen(C));
|
||||
}
|
||||
|
||||
/* function to be called outside UI context, or for redo */
|
||||
static int screen_maximize_area_exec(bContext *C, wmOperator *op)
|
||||
@@ -2499,7 +2503,7 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
|
||||
ot->idname = "SCREEN_OT_screen_full_area";
|
||||
|
||||
ot->exec = screen_maximize_area_exec;
|
||||
ot->poll = ED_operator_areaactive;
|
||||
ot->poll = screen_maximize_area_poll;
|
||||
ot->flag = 0;
|
||||
|
||||
prop = RNA_def_boolean(ot->srna, "use_hide_panels", false, "Hide Panels", "Hide all the panels");
|
||||
@@ -3021,7 +3025,8 @@ static void view3d_localview_update_rv3d(struct RegionView3D *rv3d)
|
||||
{
|
||||
if (rv3d->localvd) {
|
||||
rv3d->localvd->view = rv3d->view;
|
||||
rv3d->localvd->persp = rv3d->persp;
|
||||
rv3d->localvd->persp = ((rv3d->viewlock & RV3D_LOCK_PERSP_VIEW) && (rv3d->localvd->persp == RV3D_ORTHO)) ?
|
||||
RV3D_PERSP : rv3d->persp;
|
||||
copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);
|
||||
}
|
||||
}
|
||||
@@ -3035,6 +3040,7 @@ static void region_quadview_init_rv3d(ScrArea *sa, ARegion *ar,
|
||||
ED_view3d_lastview_store(rv3d);
|
||||
}
|
||||
|
||||
BLI_assert((rv3d->viewlock & RV3D_LOCK_PERSP_VIEW) == 0 || view != RV3D_ORTHO);
|
||||
rv3d->viewlock = viewlock;
|
||||
rv3d->view = view;
|
||||
rv3d->persp = persp;
|
||||
@@ -3081,14 +3087,16 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
|
||||
rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT;
|
||||
rv3d->viewlock = 0;
|
||||
/* allow keeping the LOCKED_SHARED flag */
|
||||
rv3d->viewlock = RV3D_IS_LOCKED_SHARED(rv3d) ? RV3D_LOCKED_SHARED : 0;
|
||||
rv3d->rflag &= ~RV3D_CLIPPING;
|
||||
|
||||
/* accumulate locks, incase they're mixed */
|
||||
for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
|
||||
if (ar_iter->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d_iter = ar_iter->regiondata;
|
||||
rv3d->viewlock_quad |= rv3d_iter->viewlock;
|
||||
rv3d->viewlock_quad |= (RV3D_IS_LOCKED_SHARED(rv3d_iter)) ?
|
||||
(rv3d_iter->viewlock & ~RV3D_LOCKED_SHARED) : rv3d_iter->viewlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3211,9 +3219,10 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot)
|
||||
/* ************** header operator ***************************** */
|
||||
static int header_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
const bScreen *screen = CTX_wm_screen(C);
|
||||
ARegion *ar = screen_find_region_type(C, RGN_TYPE_HEADER);
|
||||
|
||||
if (ar == NULL) {
|
||||
if (ar == NULL || !ED_screen_is_editable(screen)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
@@ -5024,7 +5024,7 @@ void paint_proj_stroke(
|
||||
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL))
|
||||
if (!ED_view3d_autodist(scene, CTX_wm_manager(C), CTX_wm_window(C), ar, v3d, mval_i, cursor, false, NULL))
|
||||
return;
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
|
@@ -82,6 +82,10 @@ endif()
|
||||
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
|
||||
if(WITH_INPUT_HMD)
|
||||
add_definitions(-DWITH_INPUT_HMD)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
add_definitions(-DWITH_INTERNATIONAL)
|
||||
endif()
|
||||
|
@@ -181,7 +181,12 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
|
||||
|
||||
if (ar) {
|
||||
RegionView3D *rv3d;
|
||||
if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
if ((ar->regiontype == RGN_TYPE_WINDOW) &&
|
||||
(rv3d = ar->regiondata) &&
|
||||
/* the user region may also use LOCKED_SHARED, meaning the LOCKED flag is
|
||||
* set but only because it's using the region data from another region */
|
||||
((rv3d->viewlock & RV3D_LOCKED) == 0 || RV3D_IS_LOCKED_SHARED(rv3d)))
|
||||
{
|
||||
*r_v3d = v3d;
|
||||
*r_ar = ar;
|
||||
return true;
|
||||
@@ -193,7 +198,9 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
|
||||
/* find the first unlocked rv3d */
|
||||
if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
|
||||
rv3d = ar->regiondata;
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
/* the user region may also use LOCKED_SHARED, meaning the LOCKED flag is
|
||||
* set but only because it's using the region data from another region */
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0 || RV3D_IS_LOCKED_SHARED(rv3d)) {
|
||||
ar_unlock = ar;
|
||||
if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
|
||||
ar_unlock_user = ar;
|
||||
@@ -432,13 +439,26 @@ static void view3d_free(SpaceLink *sl)
|
||||
MEM_freeN(vd->fx_settings.ssao);
|
||||
if (vd->fx_settings.dof)
|
||||
MEM_freeN(vd->fx_settings.dof);
|
||||
if (vd->fx_settings.lensdist)
|
||||
MEM_freeN(vd->fx_settings.lensdist);
|
||||
}
|
||||
|
||||
|
||||
/* spacetype; init callback */
|
||||
static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
|
||||
static void view3d_init(wmWindowManager *wm, ScrArea *sa)
|
||||
{
|
||||
#ifdef WITH_INPUT_HMD
|
||||
View3D *v3d = sa->spacedata.first;
|
||||
const wmWindow *hmd_win = wm->hmd_view.hmd_win;
|
||||
const bool is_hmd_view = hmd_win && (hmd_win->screen->areabase.first == sa);
|
||||
|
||||
/* Make sure the HMD view is initialized with the shader set in UserPrefs. */
|
||||
if (is_hmd_view && v3d->fx_settings.lensdist) {
|
||||
v3d->fx_settings.fx_flag |= GPU_FX_FLAG_LensDist;
|
||||
}
|
||||
#else
|
||||
UNUSED_VARS(wm, sa);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
@@ -477,6 +497,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
|
||||
if (v3dn->fx_settings.ssao)
|
||||
v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
|
||||
if (v3dn->fx_settings.lensdist)
|
||||
v3dn->fx_settings.lensdist = MEM_dupallocN(v3do->fx_settings.lensdist);
|
||||
|
||||
return (SpaceLink *)v3dn;
|
||||
}
|
||||
|
@@ -304,7 +304,8 @@ void ED_view3d_cameracontrol_release(
|
||||
else {
|
||||
/* Non Camera we need to reset the view back to the original location bacause the user canceled*/
|
||||
copy_qt_qt(rv3d->viewquat, vctrl->rot_backup);
|
||||
rv3d->persp = vctrl->persp_backup;
|
||||
rv3d->persp = ((rv3d->viewlock & RV3D_LOCK_PERSP_VIEW) && vctrl != RV3D_ORTHO) ?
|
||||
vctrl->persp_backup : RV3D_PERSP;
|
||||
}
|
||||
/* always, is set to zero otherwise */
|
||||
copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user