mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 09:25:31 +02:00
resolve conflicts on merge with upstream master
This commit is contained in:
commit
fcb8865d2e
79 changed files with 10605 additions and 975 deletions
|
@ -10,14 +10,16 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <OctalCode.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <EnvironmentData.h>
|
||||
#include <NodeList.h>
|
||||
#include <NodeTypes.h>
|
||||
#include <EnvironmentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <OctalCode.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SceneUtils.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <VoxelTree.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
|
@ -643,14 +645,14 @@ void* animateVoxels(void* args) {
|
|||
sendDanceFloor();
|
||||
}
|
||||
|
||||
long long end = usecTimestampNow();
|
||||
long long elapsedSeconds = (end - ::start) / 1000000;
|
||||
uint64_t end = usecTimestampNow();
|
||||
uint64_t elapsedSeconds = (end - ::start) / 1000000;
|
||||
if (::shouldShowPacketsPerSecond) {
|
||||
printf("packetsSent=%ld, bytesSent=%ld pps=%f bps=%f\n",packetsSent,bytesSent,
|
||||
(float)(packetsSent/elapsedSeconds),(float)(bytesSent/elapsedSeconds));
|
||||
}
|
||||
// dynamically sleep until we need to fire off the next set of voxels
|
||||
long long usecToSleep = ANIMATE_VOXELS_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime));
|
||||
uint64_t usecToSleep = ANIMATE_VOXELS_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime));
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
|
|
|
@ -47,7 +47,7 @@ const unsigned short MIXER_LISTEN_PORT = 55443;
|
|||
const short JITTER_BUFFER_MSECS = 12;
|
||||
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0);
|
||||
|
||||
const long long BUFFER_SEND_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
||||
const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
||||
|
||||
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||
|
@ -414,7 +414,7 @@ int main(int argc, const char* argv[]) {
|
|||
numStatCollections++;
|
||||
}
|
||||
|
||||
long long usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
|
||||
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
|
|
44
cmake/modules/FindMotionDriver.cmake
Normal file
44
cmake/modules/FindMotionDriver.cmake
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Try to find the MotionDriver library to access the InvenSense gyros
|
||||
#
|
||||
# You must provide a MOTIONDRIVER_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# MOTIONDRIVER_FOUND - system found MotionDriver
|
||||
# MOTIONDRIVER_INCLUDE_DIRS - the MotionDriver include directory
|
||||
# MOTIONDRIVER_LIBRARIES - Link this to use MotionDriver
|
||||
#
|
||||
# Created on 7/9/2013 by Andrzej Kapolka
|
||||
# Copyright (c) 2013 High Fidelity
|
||||
#
|
||||
|
||||
if (MOTIONDRIVER_LIBRARIES AND MOTIONDRIVER_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(MOTIONDRIVER_FOUND TRUE)
|
||||
else (MOTIONDRIVER_LIBRARIES AND MOTIONDRIVER_INCLUDE_DIRS)
|
||||
find_path(MOTIONDRIVER_INCLUDE_DIRS inv_mpu.h ${MOTIONDRIVER_ROOT_DIR}/include)
|
||||
|
||||
if (APPLE)
|
||||
find_library(MOTIONDRIVER_LIBRARIES libMotionDriver.a ${MOTIONDRIVER_ROOT_DIR}/lib/MacOS/)
|
||||
elseif (UNIX)
|
||||
find_library(MOTIONDRIVER_LIBRARIES libMotionDriver.a ${MOTIONDRIVER_ROOT_DIR}/lib/UNIX/)
|
||||
endif ()
|
||||
|
||||
if (MOTIONDRIVER_INCLUDE_DIRS AND MOTIONDRIVER_LIBRARIES)
|
||||
set(MOTIONDRIVER_FOUND TRUE)
|
||||
endif (MOTIONDRIVER_INCLUDE_DIRS AND MOTIONDRIVER_LIBRARIES)
|
||||
|
||||
if (MOTIONDRIVER_FOUND)
|
||||
if (NOT MOTIONDRIVER_FIND_QUIETLY)
|
||||
message(STATUS "Found MotionDriver: ${MOTIONDRIVER_LIBRARIES}")
|
||||
endif (NOT MOTIONDRIVER_FIND_QUIETLY)
|
||||
else (MOTIONDRIVER_FOUND)
|
||||
if (MOTIONDRIVER_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find MotionDriver")
|
||||
endif (MOTIONDRIVER_FIND_REQUIRED)
|
||||
endif (MOTIONDRIVER_FOUND)
|
||||
|
||||
# show the MOTIONDRIVER_INCLUDE_DIRS and MOTIONDRIVER_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(MOTIONDRIVER_INCLUDE_DIRS MOTIONDRIVER_LIBRARIES)
|
||||
|
||||
endif (MOTIONDRIVER_LIBRARIES AND MOTIONDRIVER_INCLUDE_DIRS)
|
44
cmake/modules/FindOpenNI.cmake
Normal file
44
cmake/modules/FindOpenNI.cmake
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Find the OpenNI library
|
||||
#
|
||||
# You must provide an OPENNI_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENNI_FOUND - system found OpenNI
|
||||
# OPENNI_INCLUDE_DIRS - the OpenNI include directory
|
||||
# OPENNI_LIBRARIES - Link this to use OpenNI
|
||||
#
|
||||
# Created on 6/28/2013 by Andrzej Kapolka
|
||||
# Copyright (c) 2013 High Fidelity
|
||||
#
|
||||
|
||||
if (OPENNI_LIBRARIES AND OPENNI_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(OPENNI_FOUND TRUE)
|
||||
else (OPENNI_LIBRARIES AND OPENNI_INCLUDE_DIRS)
|
||||
find_path(OPENNI_INCLUDE_DIRS XnOpenNI.h /usr/include/ni)
|
||||
|
||||
if (APPLE)
|
||||
find_library(OPENNI_LIBRARIES libOpenNI.dylib /usr/lib)
|
||||
elseif (UNIX)
|
||||
find_library(OPENNI_LIBRARIES libOpenNI.so /usr/lib)
|
||||
endif ()
|
||||
|
||||
if (OPENNI_INCLUDE_DIRS AND OPENNI_LIBRARIES)
|
||||
set(OPENNI_FOUND TRUE)
|
||||
endif (OPENNI_INCLUDE_DIRS AND OPENNI_LIBRARIES)
|
||||
|
||||
if (OPENNI_FOUND)
|
||||
if (NOT OPENNI_FIND_QUIETLY)
|
||||
message(STATUS "Found OpenNI: ${OPENNI_LIBRARIES}")
|
||||
endif (NOT OPENNI_FIND_QUIETLY)
|
||||
else (OPENNI_FOUND)
|
||||
if (OPENNI_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find OpenNI")
|
||||
endif (OPENNI_FIND_REQUIRED)
|
||||
endif (OPENNI_FOUND)
|
||||
|
||||
# show the OPENNI_INCLUDE_DIRS and OPENNI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(OPENNI_INCLUDE_DIRS OPENNI_LIBRARIES)
|
||||
|
||||
endif (OPENNI_LIBRARIES AND OPENNI_INCLUDE_DIRS)
|
|
@ -163,7 +163,7 @@ int main(int argc, const char * argv[])
|
|||
}
|
||||
|
||||
// update last receive to now
|
||||
long long timeNow = usecTimestampNow();
|
||||
uint64_t timeNow = usecTimestampNow();
|
||||
newNode->setLastHeardMicrostamp(timeNow);
|
||||
|
||||
if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY
|
||||
|
|
|
@ -126,7 +126,7 @@ int main(int argc, const char* argv[]) {
|
|||
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_HEAD_DATA);
|
||||
|
||||
timeval thisSend;
|
||||
long long numMicrosecondsSleep = 0;
|
||||
int numMicrosecondsSleep = 0;
|
||||
|
||||
int handStateTimer = 0;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ project(${TARGET_NAME})
|
|||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR)
|
||||
set(LEAP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Leap)
|
||||
set(MOTIONDRIVER_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/MotionDriver)
|
||||
set(PORTAUDIO_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/PortAudio)
|
||||
set(OPENCV_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/OpenCV)
|
||||
set(UVCCAMERACONTROL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/UVCCameraControl)
|
||||
|
@ -65,7 +66,7 @@ if (APPLE)
|
|||
|
||||
endif (APPLE)
|
||||
|
||||
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork QtOpenGL QtWebKit)
|
||||
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork QtOpenGL QtWebKit QtSvg)
|
||||
include(${QT_USE_FILE})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
||||
|
||||
|
@ -92,9 +93,19 @@ link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
|||
find_package(GLM REQUIRED)
|
||||
find_package(LibOVR)
|
||||
find_package(Leap)
|
||||
find_package(MotionDriver)
|
||||
find_package(OpenCV)
|
||||
find_package(ZLIB)
|
||||
find_package(OpenNI)
|
||||
find_package(UVCCameraControl)
|
||||
find_package(ZLIB)
|
||||
|
||||
# let the source know that we have OpenNI/NITE for Kinect
|
||||
if (OPENNI_FOUND)
|
||||
add_definitions(-DHAVE_OPENNI)
|
||||
include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENNI_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES})
|
||||
endif (OPENNI_FOUND)
|
||||
|
||||
# include headers for interface and InterfaceConfig.
|
||||
include_directories(
|
||||
|
@ -109,6 +120,7 @@ include_directories(
|
|||
${GLM_INCLUDE_DIRS}
|
||||
${LIBOVR_INCLUDE_DIRS}
|
||||
${LEAP_INCLUDE_DIRS}
|
||||
${MOTIONDRIVER_INCLUDE_DIRS}
|
||||
${OPENCV_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
@ -116,6 +128,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}")
|
|||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
${QT_LIBRARIES}
|
||||
${MOTIONDRIVER_LIBRARIES}
|
||||
${OPENCV_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
fervor
|
||||
|
|
11
interface/external/Leap/readme.txt
vendored
Normal file
11
interface/external/Leap/readme.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
Instructions for adding the Leap driver to Interface
|
||||
Eric Johnston, July 10, 2013
|
||||
|
||||
NOTE: Without doing step 2, you will crash at program start time.
|
||||
|
||||
1. Copy the Leap sdk folders (lib, include, etc.) into the interface/external/Leap folder. There should be a folder already there called "stub", and this read me.txt should be there as well.
|
||||
|
||||
2. IMPORTANT: Copy the file interface/external/Leap/lib/libc++/libLeap.dylib to /usr/lib
|
||||
|
||||
3. Delete your build directory, run cmake and build, and you should be all set.
|
14
interface/external/MotionDriver/CMakeLists.txt
vendored
Normal file
14
interface/external/MotionDriver/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(TARGET_NAME MotionDriver)
|
||||
project(${TARGET_NAME})
|
||||
|
||||
# let the library know which device we're using
|
||||
add_definitions(-DMPU9150)
|
||||
|
||||
# grab the implemenation and header files
|
||||
file(GLOB MOTION_DRIVER_SRCS include/*.h src/*.c)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
add_library(${TARGET_NAME} ${MOTION_DRIVER_SRCS})
|
218
interface/external/MotionDriver/License.txt
vendored
Normal file
218
interface/external/MotionDriver/License.txt
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
Unless you and InvenSense Corporation ("InvenSense") execute a separate written
|
||||
software license agreement governing use of the accompanying software, this
|
||||
software is licensed to you under the terms of this Software License
|
||||
Agreement ("Agreement").
|
||||
|
||||
ANY USE, REPRODUCTION OR DISTRIBUTION OF THE SOFTWARE CONSTITUTES YOUR
|
||||
ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS.
|
||||
|
||||
1.1. "InvenSense Product" means any of the proprietary integrated circuit
|
||||
product(s) sold by InvenSense with which the Software was designed to be used,
|
||||
or their successors.
|
||||
|
||||
1.2. "Licensee" means you or if you are accepting on behalf of an entity
|
||||
then the entity and its affiliates exercising rights under, and complying
|
||||
with all of the terms of this Agreement.
|
||||
|
||||
1.3. "Software" shall mean that software made available by InvenSense to
|
||||
Licensee in binary code form with this Agreement.
|
||||
|
||||
2. LICENSE GRANT; OWNERSHIP
|
||||
|
||||
2.1. License Grants. Subject to the terms and conditions of this Agreement,
|
||||
InvenSense hereby grants to Licensee a non-exclusive, non-transferable,
|
||||
royalty-free license (i) to use and integrate the Software in conjunction
|
||||
with any other software; and (ii) to reproduce and distribute the Software
|
||||
complete, unmodified and only for use with a InvenSense Product.
|
||||
|
||||
2.2. Restriction on Modification. If and to the extent that the Software is
|
||||
designed to be compliant with any published communications standard
|
||||
(including, without limitation, DOCSIS, HomePNA, IEEE, and ITU standards),
|
||||
Licensee may not make any modifications to the Software that would cause the
|
||||
Software or the accompanying InvenSense Products to be incompatible with such
|
||||
standard.
|
||||
|
||||
2.3. Restriction on Distribution. Licensee shall only distribute the
|
||||
Software (a) under the terms of this Agreement and a copy of this Agreement
|
||||
accompanies such distribution, and (b) agrees to defend and indemnify
|
||||
InvenSense and its licensors from and against any damages, costs, liabilities,
|
||||
settlement amounts and/or expenses (including attorneys' fees) incurred in
|
||||
connection with any claim, lawsuit or action by any third party that arises
|
||||
or results from the use or distribution of any and all Software by the
|
||||
Licensee except as contemplated herein.
|
||||
|
||||
2.4. Proprietary Notices. Licensee shall not remove, efface or obscure any
|
||||
copyright or trademark notices from the Software. Licensee shall include
|
||||
reproductions of the InvenSense copyright notice with each copy of the
|
||||
Software, except where such Software is embedded in a manner not readily
|
||||
accessible to the end user. Licensee acknowledges that any symbols,
|
||||
trademarks, tradenames, and service marks adopted by InvenSense to identify the
|
||||
Software belong to InvenSense and that Licensee shall have no rights therein.
|
||||
|
||||
2.5. Ownership. InvenSense shall retain all right, title and interest,
|
||||
including all intellectual property rights, in and to the Software. Licensee
|
||||
hereby covenants that it will not assert any claim that the Software created
|
||||
by or for InvenSense infringe any intellectual property right owned or
|
||||
controlled by Licensee.
|
||||
|
||||
2.6. No Other Rights Granted; Restrictions. Apart from the license rights
|
||||
expressly set forth in this Agreement, InvenSense does not grant and Licensee
|
||||
does not receive any ownership right, title or interest nor any security
|
||||
interest or other interest in any intellectual property rights relating to
|
||||
the Software, nor in any copy of any part of the foregoing. No license is
|
||||
granted to Licensee in any human readable code of the Software (source code).
|
||||
Licensee shall not (i) use, license, sell or otherwise distribute the
|
||||
Software except as provided in this Agreement, (ii) attempt to reverse
|
||||
engineer, decompile or disassemble any portion of the Software; or (iii) use
|
||||
the Software or other material in violation of any applicable law or
|
||||
regulation, including but not limited to any regulatory agency, such as FCC,
|
||||
rules.
|
||||
|
||||
3. NO WARRANTY OR SUPPORT
|
||||
|
||||
3.1. No Warranty. THE SOFTWARE IS OFFERED "AS IS," AND INVENSENSE GRANTS AND
|
||||
LICENSEE RECEIVES NO WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, BY STATUTE,
|
||||
COMMUNICATION OR CONDUCT WITH LICENSEE, OR OTHERWISE. INVENSENSE SPECIFICALLY
|
||||
DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A SPECIFIC
|
||||
PURPOSE OR NONINFRINGEMENT CONCERNING THE SOFTWARE OR ANY UPGRADES TO OR
|
||||
DOCUMENTATION FOR THE SOFTWARE. WITHOUT LIMITATION OF THE ABOVE, INVENSENSE
|
||||
GRANTS NO WARRANTY THAT THE SOFTWARE IS ERROR-FREE OR WILL OPERATE WITHOUT
|
||||
INTERRUPTION, AND GRANTS NO WARRANTY REGARDING ITS USE OR THE RESULTS
|
||||
THEREFROM INCLUDING, WITHOUT LIMITATION, ITS CORRECTNESS, ACCURACY OR
|
||||
RELIABILITY.
|
||||
|
||||
3.2. No Support. Nothing in this agreement shall obligate InvenSense to
|
||||
provide any support for the Software. InvenSense may, but shall be under no
|
||||
obligation to, correct any defects in the Software and/or provide updates to
|
||||
licensees of the Software. Licensee shall make reasonable efforts to
|
||||
promptly report to InvenSense any defects it finds in the Software, as an aid
|
||||
to creating improved revisions of the Software.
|
||||
|
||||
3.3. Dangerous Applications. The Software is not designed, intended, or
|
||||
certified for use in components of systems intended for the operation of
|
||||
weapons, weapons systems, nuclear installations, means of mass
|
||||
transportation, aviation, life-support computers or equipment (including
|
||||
resuscitation equipment and surgical implants), pollution control, hazardous
|
||||
substances management, or for any other dangerous application in which the
|
||||
failure of the Software could create a situation where personal injury or
|
||||
death may occur. Licensee understands that use of the Software in such
|
||||
applications is fully at the risk of Licensee.
|
||||
|
||||
4. TERM AND TERMINATION
|
||||
|
||||
4.1. Termination. This Agreement will automatically terminate if Licensee
|
||||
fails to comply with any of the terms and conditions hereof. In such event,
|
||||
Licensee must destroy all copies of the Software and all of its component
|
||||
parts.
|
||||
|
||||
4.2. Effect Of Termination. Upon any termination of this Agreement, the
|
||||
rights and licenses granted to Licensee under this Agreement shall
|
||||
immediately terminate.
|
||||
|
||||
4.3. Survival. The rights and obligations under this Agreement which by
|
||||
their nature should survive termination will remain in effect after
|
||||
expiration or termination of this Agreement.
|
||||
|
||||
5. CONFIDENTIALITY
|
||||
|
||||
5.1. Obligations. Licensee acknowledges and agrees that any documentation
|
||||
relating to the Software, and any other information (if such other
|
||||
information is identified as confidential or should be recognized as
|
||||
confidential under the circumstances) provided to Licensee by InvenSense
|
||||
hereunder (collectively, "Confidential Information") constitute the
|
||||
confidential and proprietary information of InvenSense, and that Licensee's
|
||||
protection thereof is an essential condition to Licensee's use and possession
|
||||
of the Software. Licensee shall retain all Confidential Information in
|
||||
strict confidence and not disclose it to any third party or use it in any way
|
||||
except under a written agreement with terms and conditions at least as
|
||||
protective as the terms of this Section. Licensee will exercise at least the
|
||||
same amount of diligence in preserving the secrecy of the Confidential
|
||||
Information as it uses in preserving the secrecy of its own most valuable
|
||||
confidential information, but in no event less than reasonable diligence.
|
||||
Information shall not be considered Confidential Information if and to the
|
||||
extent that it: (i) was in the public domain at the time it was disclosed or
|
||||
has entered the public domain through no fault of Licensee; (ii) was known to
|
||||
Licensee, without restriction, at the time of disclosure as proven by the
|
||||
files of Licensee in existence at the time of disclosure; or (iii) becomes
|
||||
known to Licensee, without restriction, from a source other than InvenSense
|
||||
without breach of this Agreement by Licensee and otherwise not in violation
|
||||
of InvenSense's rights.
|
||||
|
||||
5.2. Return of Confidential Information. Notwithstanding the foregoing, all
|
||||
documents and other tangible objects containing or representing InvenSense
|
||||
Confidential Information and all copies thereof which are in the possession
|
||||
of Licensee shall be and remain the property of InvenSense, and shall be
|
||||
promptly returned to InvenSense upon written request by InvenSense or upon
|
||||
termination of this Agreement.
|
||||
|
||||
6. LIMITATION OF LIABILITY
|
||||
TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL INVENSENSE OR ANY OF
|
||||
INVENSENSE'S LICENSORS HAVE ANY LIABILITY FOR ANY INDIRECT, INCIDENTAL,
|
||||
SPECIAL, OR CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER FOR BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR
|
||||
OTHERWISE, ARISING OUT OF THIS AGREEMENT, INCLUDING BUT NOT LIMITED TO LOSS
|
||||
OF PROFITS, EVEN IF SUCH PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES. IN NO EVENT WILL INVENSENSE'S LIABILITY WHETHER IN CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), OR OTHERWISE, EXCEED THE AMOUNT PAID BY LICENSEE FOR
|
||||
SOFTWARE UNDER THIS AGREEMENT. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING
|
||||
ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
|
||||
|
||||
7. MISCELLANEOUS
|
||||
|
||||
7.1. Export Regulations. YOU UNDERSTAND AND AGREE THAT THE SOFTWARE IS
|
||||
SUBJECT TO UNITED STATES AND OTHER APPLICABLE EXPORT-RELATED LAWS AND
|
||||
REGULATIONS AND THAT YOU MAY NOT EXPORT, RE-EXPORT OR TRANSFER THE SOFTWARE
|
||||
OR ANY DIRECT PRODUCT OF THE SOFTWARE EXCEPT AS PERMITTED UNDER THOSE LAWS.
|
||||
WITHOUT LIMITING THE FOREGOING, EXPORT, RE-EXPORT OR TRANSFER OF THE SOFTWARE
|
||||
TO CUBA, IRAN, NORTH KOREA, SUDAN AND SYRIA IS PROHIBITED.
|
||||
|
||||
7.2 Assignment. This Agreement shall be binding upon and inure to the
|
||||
benefit of the parties and their respective successors and assigns, provided,
|
||||
however that Licensee may not assign this Agreement or any rights or
|
||||
obligation hereunder, directly or indirectly, by operation of law or
|
||||
otherwise, without the prior written consent of InvenSense, and any such
|
||||
attempted assignment shall be void. Notwithstanding the foregoing, Licensee
|
||||
may assign this Agreement to a successor to all or substantially all of its
|
||||
business or assets to which this Agreement relates that is not a competitor
|
||||
of InvenSense.
|
||||
|
||||
7.3. Governing Law; Venue. This Agreement shall be governed by the laws of
|
||||
California without regard to any conflict-of-laws rules, and the United
|
||||
Nations Convention on Contracts for the International Sale of Goods is hereby
|
||||
excluded. The sole jurisdiction and venue for actions related to the subject
|
||||
matter hereof shall be the state and federal courts located in the County of
|
||||
Orange, California, and both parties hereby consent to such jurisdiction and
|
||||
venue.
|
||||
|
||||
7.4. Severability. All terms and provisions of this Agreement shall, if
|
||||
possible, be construed in a manner which makes them valid, but in the event
|
||||
any term or provision of this Agreement is found by a court of competent
|
||||
jurisdiction to be illegal or unenforceable, the validity or enforceability
|
||||
of the remainder of this Agreement shall not be affected if the illegal or
|
||||
unenforceable provision does not materially affect the intent of this
|
||||
Agreement. If the illegal or unenforceable provision materially affects the
|
||||
intent of the parties to this Agreement, this Agreement shall become
|
||||
terminated.
|
||||
|
||||
7.5. Equitable Relief. Licensee hereby acknowledges that its breach of this
|
||||
Agreement would cause irreparable harm and significant injury to InvenSense
|
||||
that may be difficult to ascertain and that a remedy at law would be
|
||||
inadequate. Accordingly, Licensee agrees that InvenSense shall have the right
|
||||
to seek and obtain immediate injunctive relief to enforce obligations under
|
||||
the Agreement in addition to any other rights and remedies it may have.
|
||||
|
||||
7.6. Waiver. The waiver of, or failure to enforce, any breach or default
|
||||
hereunder shall not constitute the waiver of any other or subsequent breach
|
||||
or default.
|
||||
|
||||
7.7. Entire Agreement. This Agreement sets forth the entire Agreement
|
||||
between the parties and supersedes any and all prior proposals, agreements
|
||||
and representations between them, whether written or oral concerning the
|
||||
Software. This Agreement may be changed only by mutual agreement of the
|
||||
parties in writing.
|
||||
|
||||
|
494
interface/external/MotionDriver/include/dmpKey.h
vendored
Normal file
494
interface/external/MotionDriver/include/dmpKey.h
vendored
Normal file
|
@ -0,0 +1,494 @@
|
|||
/*
|
||||
$License:
|
||||
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
|
||||
$
|
||||
*/
|
||||
#ifndef DMPKEY_H__
|
||||
#define DMPKEY_H__
|
||||
|
||||
#define KEY_CFG_25 (0)
|
||||
#define KEY_CFG_24 (KEY_CFG_25 + 1)
|
||||
#define KEY_CFG_26 (KEY_CFG_24 + 1)
|
||||
#define KEY_CFG_27 (KEY_CFG_26 + 1)
|
||||
#define KEY_CFG_21 (KEY_CFG_27 + 1)
|
||||
#define KEY_CFG_20 (KEY_CFG_21 + 1)
|
||||
#define KEY_CFG_TAP4 (KEY_CFG_20 + 1)
|
||||
#define KEY_CFG_TAP5 (KEY_CFG_TAP4 + 1)
|
||||
#define KEY_CFG_TAP6 (KEY_CFG_TAP5 + 1)
|
||||
#define KEY_CFG_TAP7 (KEY_CFG_TAP6 + 1)
|
||||
#define KEY_CFG_TAP0 (KEY_CFG_TAP7 + 1)
|
||||
#define KEY_CFG_TAP1 (KEY_CFG_TAP0 + 1)
|
||||
#define KEY_CFG_TAP2 (KEY_CFG_TAP1 + 1)
|
||||
#define KEY_CFG_TAP3 (KEY_CFG_TAP2 + 1)
|
||||
#define KEY_CFG_TAP_QUANTIZE (KEY_CFG_TAP3 + 1)
|
||||
#define KEY_CFG_TAP_JERK (KEY_CFG_TAP_QUANTIZE + 1)
|
||||
#define KEY_CFG_DR_INT (KEY_CFG_TAP_JERK + 1)
|
||||
#define KEY_CFG_AUTH (KEY_CFG_DR_INT + 1)
|
||||
#define KEY_CFG_TAP_SAVE_ACCB (KEY_CFG_AUTH + 1)
|
||||
#define KEY_CFG_TAP_CLEAR_STICKY (KEY_CFG_TAP_SAVE_ACCB + 1)
|
||||
#define KEY_CFG_FIFO_ON_EVENT (KEY_CFG_TAP_CLEAR_STICKY + 1)
|
||||
#define KEY_FCFG_ACCEL_INPUT (KEY_CFG_FIFO_ON_EVENT + 1)
|
||||
#define KEY_FCFG_ACCEL_INIT (KEY_FCFG_ACCEL_INPUT + 1)
|
||||
#define KEY_CFG_23 (KEY_FCFG_ACCEL_INIT + 1)
|
||||
#define KEY_FCFG_1 (KEY_CFG_23 + 1)
|
||||
#define KEY_FCFG_3 (KEY_FCFG_1 + 1)
|
||||
#define KEY_FCFG_2 (KEY_FCFG_3 + 1)
|
||||
#define KEY_CFG_3D (KEY_FCFG_2 + 1)
|
||||
#define KEY_CFG_3B (KEY_CFG_3D + 1)
|
||||
#define KEY_CFG_3C (KEY_CFG_3B + 1)
|
||||
#define KEY_FCFG_5 (KEY_CFG_3C + 1)
|
||||
#define KEY_FCFG_4 (KEY_FCFG_5 + 1)
|
||||
#define KEY_FCFG_7 (KEY_FCFG_4 + 1)
|
||||
#define KEY_FCFG_FSCALE (KEY_FCFG_7 + 1)
|
||||
#define KEY_FCFG_AZ (KEY_FCFG_FSCALE + 1)
|
||||
#define KEY_FCFG_6 (KEY_FCFG_AZ + 1)
|
||||
#define KEY_FCFG_LSB4 (KEY_FCFG_6 + 1)
|
||||
#define KEY_CFG_12 (KEY_FCFG_LSB4 + 1)
|
||||
#define KEY_CFG_14 (KEY_CFG_12 + 1)
|
||||
#define KEY_CFG_15 (KEY_CFG_14 + 1)
|
||||
#define KEY_CFG_16 (KEY_CFG_15 + 1)
|
||||
#define KEY_CFG_18 (KEY_CFG_16 + 1)
|
||||
#define KEY_CFG_6 (KEY_CFG_18 + 1)
|
||||
#define KEY_CFG_7 (KEY_CFG_6 + 1)
|
||||
#define KEY_CFG_4 (KEY_CFG_7 + 1)
|
||||
#define KEY_CFG_5 (KEY_CFG_4 + 1)
|
||||
#define KEY_CFG_2 (KEY_CFG_5 + 1)
|
||||
#define KEY_CFG_3 (KEY_CFG_2 + 1)
|
||||
#define KEY_CFG_1 (KEY_CFG_3 + 1)
|
||||
#define KEY_CFG_EXTERNAL (KEY_CFG_1 + 1)
|
||||
#define KEY_CFG_8 (KEY_CFG_EXTERNAL + 1)
|
||||
#define KEY_CFG_9 (KEY_CFG_8 + 1)
|
||||
#define KEY_CFG_ORIENT_3 (KEY_CFG_9 + 1)
|
||||
#define KEY_CFG_ORIENT_2 (KEY_CFG_ORIENT_3 + 1)
|
||||
#define KEY_CFG_ORIENT_1 (KEY_CFG_ORIENT_2 + 1)
|
||||
#define KEY_CFG_GYRO_SOURCE (KEY_CFG_ORIENT_1 + 1)
|
||||
#define KEY_CFG_ORIENT_IRQ_1 (KEY_CFG_GYRO_SOURCE + 1)
|
||||
#define KEY_CFG_ORIENT_IRQ_2 (KEY_CFG_ORIENT_IRQ_1 + 1)
|
||||
#define KEY_CFG_ORIENT_IRQ_3 (KEY_CFG_ORIENT_IRQ_2 + 1)
|
||||
#define KEY_FCFG_MAG_VAL (KEY_CFG_ORIENT_IRQ_3 + 1)
|
||||
#define KEY_FCFG_MAG_MOV (KEY_FCFG_MAG_VAL + 1)
|
||||
#define KEY_CFG_LP_QUAT (KEY_FCFG_MAG_MOV + 1)
|
||||
|
||||
/* MPU6050 keys */
|
||||
#define KEY_CFG_ACCEL_FILTER (KEY_CFG_LP_QUAT + 1)
|
||||
#define KEY_CFG_MOTION_BIAS (KEY_CFG_ACCEL_FILTER + 1)
|
||||
#define KEY_TEMPLABEL (KEY_CFG_MOTION_BIAS + 1)
|
||||
|
||||
#define KEY_D_0_22 (KEY_TEMPLABEL + 1)
|
||||
#define KEY_D_0_24 (KEY_D_0_22 + 1)
|
||||
#define KEY_D_0_36 (KEY_D_0_24 + 1)
|
||||
#define KEY_D_0_52 (KEY_D_0_36 + 1)
|
||||
#define KEY_D_0_96 (KEY_D_0_52 + 1)
|
||||
#define KEY_D_0_104 (KEY_D_0_96 + 1)
|
||||
#define KEY_D_0_108 (KEY_D_0_104 + 1)
|
||||
#define KEY_D_0_163 (KEY_D_0_108 + 1)
|
||||
#define KEY_D_0_188 (KEY_D_0_163 + 1)
|
||||
#define KEY_D_0_192 (KEY_D_0_188 + 1)
|
||||
#define KEY_D_0_224 (KEY_D_0_192 + 1)
|
||||
#define KEY_D_0_228 (KEY_D_0_224 + 1)
|
||||
#define KEY_D_0_232 (KEY_D_0_228 + 1)
|
||||
#define KEY_D_0_236 (KEY_D_0_232 + 1)
|
||||
|
||||
#define KEY_DMP_PREVPTAT (KEY_D_0_236 + 1)
|
||||
#define KEY_D_1_2 (KEY_DMP_PREVPTAT + 1)
|
||||
#define KEY_D_1_4 (KEY_D_1_2 + 1)
|
||||
#define KEY_D_1_8 (KEY_D_1_4 + 1)
|
||||
#define KEY_D_1_10 (KEY_D_1_8 + 1)
|
||||
#define KEY_D_1_24 (KEY_D_1_10 + 1)
|
||||
#define KEY_D_1_28 (KEY_D_1_24 + 1)
|
||||
#define KEY_D_1_36 (KEY_D_1_28 + 1)
|
||||
#define KEY_D_1_40 (KEY_D_1_36 + 1)
|
||||
#define KEY_D_1_44 (KEY_D_1_40 + 1)
|
||||
#define KEY_D_1_72 (KEY_D_1_44 + 1)
|
||||
#define KEY_D_1_74 (KEY_D_1_72 + 1)
|
||||
#define KEY_D_1_79 (KEY_D_1_74 + 1)
|
||||
#define KEY_D_1_88 (KEY_D_1_79 + 1)
|
||||
#define KEY_D_1_90 (KEY_D_1_88 + 1)
|
||||
#define KEY_D_1_92 (KEY_D_1_90 + 1)
|
||||
#define KEY_D_1_96 (KEY_D_1_92 + 1)
|
||||
#define KEY_D_1_98 (KEY_D_1_96 + 1)
|
||||
#define KEY_D_1_100 (KEY_D_1_98 + 1)
|
||||
#define KEY_D_1_106 (KEY_D_1_100 + 1)
|
||||
#define KEY_D_1_108 (KEY_D_1_106 + 1)
|
||||
#define KEY_D_1_112 (KEY_D_1_108 + 1)
|
||||
#define KEY_D_1_128 (KEY_D_1_112 + 1)
|
||||
#define KEY_D_1_152 (KEY_D_1_128 + 1)
|
||||
#define KEY_D_1_160 (KEY_D_1_152 + 1)
|
||||
#define KEY_D_1_168 (KEY_D_1_160 + 1)
|
||||
#define KEY_D_1_175 (KEY_D_1_168 + 1)
|
||||
#define KEY_D_1_176 (KEY_D_1_175 + 1)
|
||||
#define KEY_D_1_178 (KEY_D_1_176 + 1)
|
||||
#define KEY_D_1_179 (KEY_D_1_178 + 1)
|
||||
#define KEY_D_1_218 (KEY_D_1_179 + 1)
|
||||
#define KEY_D_1_232 (KEY_D_1_218 + 1)
|
||||
#define KEY_D_1_236 (KEY_D_1_232 + 1)
|
||||
#define KEY_D_1_240 (KEY_D_1_236 + 1)
|
||||
#define KEY_D_1_244 (KEY_D_1_240 + 1)
|
||||
#define KEY_D_1_250 (KEY_D_1_244 + 1)
|
||||
#define KEY_D_1_252 (KEY_D_1_250 + 1)
|
||||
#define KEY_D_2_12 (KEY_D_1_252 + 1)
|
||||
#define KEY_D_2_96 (KEY_D_2_12 + 1)
|
||||
#define KEY_D_2_108 (KEY_D_2_96 + 1)
|
||||
#define KEY_D_2_208 (KEY_D_2_108 + 1)
|
||||
#define KEY_FLICK_MSG (KEY_D_2_208 + 1)
|
||||
#define KEY_FLICK_COUNTER (KEY_FLICK_MSG + 1)
|
||||
#define KEY_FLICK_LOWER (KEY_FLICK_COUNTER + 1)
|
||||
#define KEY_CFG_FLICK_IN (KEY_FLICK_LOWER + 1)
|
||||
#define KEY_FLICK_UPPER (KEY_CFG_FLICK_IN + 1)
|
||||
#define KEY_CGNOTICE_INTR (KEY_FLICK_UPPER + 1)
|
||||
#define KEY_D_2_224 (KEY_CGNOTICE_INTR + 1)
|
||||
#define KEY_D_2_244 (KEY_D_2_224 + 1)
|
||||
#define KEY_D_2_248 (KEY_D_2_244 + 1)
|
||||
#define KEY_D_2_252 (KEY_D_2_248 + 1)
|
||||
|
||||
#define KEY_D_GYRO_BIAS_X (KEY_D_2_252 + 1)
|
||||
#define KEY_D_GYRO_BIAS_Y (KEY_D_GYRO_BIAS_X + 1)
|
||||
#define KEY_D_GYRO_BIAS_Z (KEY_D_GYRO_BIAS_Y + 1)
|
||||
#define KEY_D_ACC_BIAS_X (KEY_D_GYRO_BIAS_Z + 1)
|
||||
#define KEY_D_ACC_BIAS_Y (KEY_D_ACC_BIAS_X + 1)
|
||||
#define KEY_D_ACC_BIAS_Z (KEY_D_ACC_BIAS_Y + 1)
|
||||
#define KEY_D_GYRO_ENABLE (KEY_D_ACC_BIAS_Z + 1)
|
||||
#define KEY_D_ACCEL_ENABLE (KEY_D_GYRO_ENABLE + 1)
|
||||
#define KEY_D_QUAT_ENABLE (KEY_D_ACCEL_ENABLE +1)
|
||||
#define KEY_D_OUTPUT_ENABLE (KEY_D_QUAT_ENABLE + 1)
|
||||
#define KEY_D_CR_TIME_G (KEY_D_OUTPUT_ENABLE + 1)
|
||||
#define KEY_D_CR_TIME_A (KEY_D_CR_TIME_G + 1)
|
||||
#define KEY_D_CR_TIME_Q (KEY_D_CR_TIME_A + 1)
|
||||
#define KEY_D_CS_TAX (KEY_D_CR_TIME_Q + 1)
|
||||
#define KEY_D_CS_TAY (KEY_D_CS_TAX + 1)
|
||||
#define KEY_D_CS_TAZ (KEY_D_CS_TAY + 1)
|
||||
#define KEY_D_CS_TGX (KEY_D_CS_TAZ + 1)
|
||||
#define KEY_D_CS_TGY (KEY_D_CS_TGX + 1)
|
||||
#define KEY_D_CS_TGZ (KEY_D_CS_TGY + 1)
|
||||
#define KEY_D_CS_TQ0 (KEY_D_CS_TGZ + 1)
|
||||
#define KEY_D_CS_TQ1 (KEY_D_CS_TQ0 + 1)
|
||||
#define KEY_D_CS_TQ2 (KEY_D_CS_TQ1 + 1)
|
||||
#define KEY_D_CS_TQ3 (KEY_D_CS_TQ2 + 1)
|
||||
|
||||
/* Compass keys */
|
||||
#define KEY_CPASS_BIAS_X (KEY_D_CS_TQ3 + 1)
|
||||
#define KEY_CPASS_BIAS_Y (KEY_CPASS_BIAS_X + 1)
|
||||
#define KEY_CPASS_BIAS_Z (KEY_CPASS_BIAS_Y + 1)
|
||||
#define KEY_CPASS_MTX_00 (KEY_CPASS_BIAS_Z + 1)
|
||||
#define KEY_CPASS_MTX_01 (KEY_CPASS_MTX_00 + 1)
|
||||
#define KEY_CPASS_MTX_02 (KEY_CPASS_MTX_01 + 1)
|
||||
#define KEY_CPASS_MTX_10 (KEY_CPASS_MTX_02 + 1)
|
||||
#define KEY_CPASS_MTX_11 (KEY_CPASS_MTX_10 + 1)
|
||||
#define KEY_CPASS_MTX_12 (KEY_CPASS_MTX_11 + 1)
|
||||
#define KEY_CPASS_MTX_20 (KEY_CPASS_MTX_12 + 1)
|
||||
#define KEY_CPASS_MTX_21 (KEY_CPASS_MTX_20 + 1)
|
||||
#define KEY_CPASS_MTX_22 (KEY_CPASS_MTX_21 + 1)
|
||||
|
||||
/* Gesture Keys */
|
||||
#define KEY_DMP_TAPW_MIN (KEY_CPASS_MTX_22 + 1)
|
||||
#define KEY_DMP_TAP_THR_X (KEY_DMP_TAPW_MIN + 1)
|
||||
#define KEY_DMP_TAP_THR_Y (KEY_DMP_TAP_THR_X + 1)
|
||||
#define KEY_DMP_TAP_THR_Z (KEY_DMP_TAP_THR_Y + 1)
|
||||
#define KEY_DMP_SH_TH_Y (KEY_DMP_TAP_THR_Z + 1)
|
||||
#define KEY_DMP_SH_TH_X (KEY_DMP_SH_TH_Y + 1)
|
||||
#define KEY_DMP_SH_TH_Z (KEY_DMP_SH_TH_X + 1)
|
||||
#define KEY_DMP_ORIENT (KEY_DMP_SH_TH_Z + 1)
|
||||
#define KEY_D_ACT0 (KEY_DMP_ORIENT + 1)
|
||||
#define KEY_D_ACSX (KEY_D_ACT0 + 1)
|
||||
#define KEY_D_ACSY (KEY_D_ACSX + 1)
|
||||
#define KEY_D_ACSZ (KEY_D_ACSY + 1)
|
||||
|
||||
#define KEY_X_GRT_Y_TMP (KEY_D_ACSZ + 1)
|
||||
#define KEY_SKIP_X_GRT_Y_TMP (KEY_X_GRT_Y_TMP + 1)
|
||||
#define KEY_SKIP_END_COMPARE (KEY_SKIP_X_GRT_Y_TMP + 1)
|
||||
#define KEY_END_COMPARE_Y_X_TMP2 (KEY_SKIP_END_COMPARE + 1)
|
||||
#define KEY_CFG_ANDROID_ORIENT_INT (KEY_END_COMPARE_Y_X_TMP2 + 1)
|
||||
#define KEY_NO_ORIENT_INTERRUPT (KEY_CFG_ANDROID_ORIENT_INT + 1)
|
||||
#define KEY_END_COMPARE_Y_X_TMP (KEY_NO_ORIENT_INTERRUPT + 1)
|
||||
#define KEY_END_ORIENT_1 (KEY_END_COMPARE_Y_X_TMP + 1)
|
||||
#define KEY_END_COMPARE_Y_X (KEY_END_ORIENT_1 + 1)
|
||||
#define KEY_END_ORIENT (KEY_END_COMPARE_Y_X + 1)
|
||||
#define KEY_X_GRT_Y (KEY_END_ORIENT + 1)
|
||||
#define KEY_NOT_TIME_MINUS_1 (KEY_X_GRT_Y + 1)
|
||||
#define KEY_END_COMPARE_Y_X_TMP3 (KEY_NOT_TIME_MINUS_1 + 1)
|
||||
#define KEY_X_GRT_Y_TMP2 (KEY_END_COMPARE_Y_X_TMP3 + 1)
|
||||
|
||||
/* Authenticate Keys */
|
||||
#define KEY_D_AUTH_OUT (KEY_X_GRT_Y_TMP2 + 1)
|
||||
#define KEY_D_AUTH_IN (KEY_D_AUTH_OUT + 1)
|
||||
#define KEY_D_AUTH_A (KEY_D_AUTH_IN + 1)
|
||||
#define KEY_D_AUTH_B (KEY_D_AUTH_A + 1)
|
||||
|
||||
/* Pedometer standalone only keys */
|
||||
#define KEY_D_PEDSTD_BP_B (KEY_D_AUTH_B + 1)
|
||||
#define KEY_D_PEDSTD_HP_A (KEY_D_PEDSTD_BP_B + 1)
|
||||
#define KEY_D_PEDSTD_HP_B (KEY_D_PEDSTD_HP_A + 1)
|
||||
#define KEY_D_PEDSTD_BP_A4 (KEY_D_PEDSTD_HP_B + 1)
|
||||
#define KEY_D_PEDSTD_BP_A3 (KEY_D_PEDSTD_BP_A4 + 1)
|
||||
#define KEY_D_PEDSTD_BP_A2 (KEY_D_PEDSTD_BP_A3 + 1)
|
||||
#define KEY_D_PEDSTD_BP_A1 (KEY_D_PEDSTD_BP_A2 + 1)
|
||||
#define KEY_D_PEDSTD_INT_THRSH (KEY_D_PEDSTD_BP_A1 + 1)
|
||||
#define KEY_D_PEDSTD_CLIP (KEY_D_PEDSTD_INT_THRSH + 1)
|
||||
#define KEY_D_PEDSTD_SB (KEY_D_PEDSTD_CLIP + 1)
|
||||
#define KEY_D_PEDSTD_SB_TIME (KEY_D_PEDSTD_SB + 1)
|
||||
#define KEY_D_PEDSTD_PEAKTHRSH (KEY_D_PEDSTD_SB_TIME + 1)
|
||||
#define KEY_D_PEDSTD_TIML (KEY_D_PEDSTD_PEAKTHRSH + 1)
|
||||
#define KEY_D_PEDSTD_TIMH (KEY_D_PEDSTD_TIML + 1)
|
||||
#define KEY_D_PEDSTD_PEAK (KEY_D_PEDSTD_TIMH + 1)
|
||||
#define KEY_D_PEDSTD_TIMECTR (KEY_D_PEDSTD_PEAK + 1)
|
||||
#define KEY_D_PEDSTD_STEPCTR (KEY_D_PEDSTD_TIMECTR + 1)
|
||||
#define KEY_D_PEDSTD_WALKTIME (KEY_D_PEDSTD_STEPCTR + 1)
|
||||
#define KEY_D_PEDSTD_DECI (KEY_D_PEDSTD_WALKTIME + 1)
|
||||
|
||||
/*Host Based No Motion*/
|
||||
#define KEY_D_HOST_NO_MOT (KEY_D_PEDSTD_DECI + 1)
|
||||
|
||||
/* EIS keys */
|
||||
#define KEY_P_EIS_FIFO_FOOTER (KEY_D_HOST_NO_MOT + 1)
|
||||
#define KEY_P_EIS_FIFO_YSHIFT (KEY_P_EIS_FIFO_FOOTER + 1)
|
||||
#define KEY_P_EIS_DATA_RATE (KEY_P_EIS_FIFO_YSHIFT + 1)
|
||||
#define KEY_P_EIS_FIFO_XSHIFT (KEY_P_EIS_DATA_RATE + 1)
|
||||
#define KEY_P_EIS_FIFO_SYNC (KEY_P_EIS_FIFO_XSHIFT + 1)
|
||||
#define KEY_P_EIS_FIFO_ZSHIFT (KEY_P_EIS_FIFO_SYNC + 1)
|
||||
#define KEY_P_EIS_FIFO_READY (KEY_P_EIS_FIFO_ZSHIFT + 1)
|
||||
#define KEY_DMP_FOOTER (KEY_P_EIS_FIFO_READY + 1)
|
||||
#define KEY_DMP_INTX_HC (KEY_DMP_FOOTER + 1)
|
||||
#define KEY_DMP_INTX_PH (KEY_DMP_INTX_HC + 1)
|
||||
#define KEY_DMP_INTX_SH (KEY_DMP_INTX_PH + 1)
|
||||
#define KEY_DMP_AINV_SH (KEY_DMP_INTX_SH + 1)
|
||||
#define KEY_DMP_A_INV_XH (KEY_DMP_AINV_SH + 1)
|
||||
#define KEY_DMP_AINV_PH (KEY_DMP_A_INV_XH + 1)
|
||||
#define KEY_DMP_CTHX_H (KEY_DMP_AINV_PH + 1)
|
||||
#define KEY_DMP_CTHY_H (KEY_DMP_CTHX_H + 1)
|
||||
#define KEY_DMP_CTHZ_H (KEY_DMP_CTHY_H + 1)
|
||||
#define KEY_DMP_NCTHX_H (KEY_DMP_CTHZ_H + 1)
|
||||
#define KEY_DMP_NCTHY_H (KEY_DMP_NCTHX_H + 1)
|
||||
#define KEY_DMP_NCTHZ_H (KEY_DMP_NCTHY_H + 1)
|
||||
#define KEY_DMP_CTSQ_XH (KEY_DMP_NCTHZ_H + 1)
|
||||
#define KEY_DMP_CTSQ_YH (KEY_DMP_CTSQ_XH + 1)
|
||||
#define KEY_DMP_CTSQ_ZH (KEY_DMP_CTSQ_YH + 1)
|
||||
#define KEY_DMP_INTX_H (KEY_DMP_CTSQ_ZH + 1)
|
||||
#define KEY_DMP_INTY_H (KEY_DMP_INTX_H + 1)
|
||||
#define KEY_DMP_INTZ_H (KEY_DMP_INTY_H + 1)
|
||||
//#define KEY_DMP_HPX_H (KEY_DMP_INTZ_H + 1)
|
||||
//#define KEY_DMP_HPY_H (KEY_DMP_HPX_H + 1)
|
||||
//#define KEY_DMP_HPZ_H (KEY_DMP_HPY_H + 1)
|
||||
|
||||
/* Stream keys */
|
||||
#define KEY_STREAM_P_GYRO_Z (KEY_DMP_INTZ_H + 1)
|
||||
#define KEY_STREAM_P_GYRO_Y (KEY_STREAM_P_GYRO_Z + 1)
|
||||
#define KEY_STREAM_P_GYRO_X (KEY_STREAM_P_GYRO_Y + 1)
|
||||
#define KEY_STREAM_P_TEMP (KEY_STREAM_P_GYRO_X + 1)
|
||||
#define KEY_STREAM_P_AUX_Y (KEY_STREAM_P_TEMP + 1)
|
||||
#define KEY_STREAM_P_AUX_X (KEY_STREAM_P_AUX_Y + 1)
|
||||
#define KEY_STREAM_P_AUX_Z (KEY_STREAM_P_AUX_X + 1)
|
||||
#define KEY_STREAM_P_ACCEL_Y (KEY_STREAM_P_AUX_Z + 1)
|
||||
#define KEY_STREAM_P_ACCEL_X (KEY_STREAM_P_ACCEL_Y + 1)
|
||||
#define KEY_STREAM_P_FOOTER (KEY_STREAM_P_ACCEL_X + 1)
|
||||
#define KEY_STREAM_P_ACCEL_Z (KEY_STREAM_P_FOOTER + 1)
|
||||
|
||||
#define NUM_KEYS (KEY_STREAM_P_ACCEL_Z + 1)
|
||||
|
||||
typedef struct {
|
||||
unsigned short key;
|
||||
unsigned short addr;
|
||||
} tKeyLabel;
|
||||
|
||||
#define DINA0A 0x0a
|
||||
#define DINA22 0x22
|
||||
#define DINA42 0x42
|
||||
#define DINA5A 0x5a
|
||||
|
||||
#define DINA06 0x06
|
||||
#define DINA0E 0x0e
|
||||
#define DINA16 0x16
|
||||
#define DINA1E 0x1e
|
||||
#define DINA26 0x26
|
||||
#define DINA2E 0x2e
|
||||
#define DINA36 0x36
|
||||
#define DINA3E 0x3e
|
||||
#define DINA46 0x46
|
||||
#define DINA4E 0x4e
|
||||
#define DINA56 0x56
|
||||
#define DINA5E 0x5e
|
||||
#define DINA66 0x66
|
||||
#define DINA6E 0x6e
|
||||
#define DINA76 0x76
|
||||
#define DINA7E 0x7e
|
||||
|
||||
#define DINA00 0x00
|
||||
#define DINA08 0x08
|
||||
#define DINA10 0x10
|
||||
#define DINA18 0x18
|
||||
#define DINA20 0x20
|
||||
#define DINA28 0x28
|
||||
#define DINA30 0x30
|
||||
#define DINA38 0x38
|
||||
#define DINA40 0x40
|
||||
#define DINA48 0x48
|
||||
#define DINA50 0x50
|
||||
#define DINA58 0x58
|
||||
#define DINA60 0x60
|
||||
#define DINA68 0x68
|
||||
#define DINA70 0x70
|
||||
#define DINA78 0x78
|
||||
|
||||
#define DINA04 0x04
|
||||
#define DINA0C 0x0c
|
||||
#define DINA14 0x14
|
||||
#define DINA1C 0x1C
|
||||
#define DINA24 0x24
|
||||
#define DINA2C 0x2c
|
||||
#define DINA34 0x34
|
||||
#define DINA3C 0x3c
|
||||
#define DINA44 0x44
|
||||
#define DINA4C 0x4c
|
||||
#define DINA54 0x54
|
||||
#define DINA5C 0x5c
|
||||
#define DINA64 0x64
|
||||
#define DINA6C 0x6c
|
||||
#define DINA74 0x74
|
||||
#define DINA7C 0x7c
|
||||
|
||||
#define DINA01 0x01
|
||||
#define DINA09 0x09
|
||||
#define DINA11 0x11
|
||||
#define DINA19 0x19
|
||||
#define DINA21 0x21
|
||||
#define DINA29 0x29
|
||||
#define DINA31 0x31
|
||||
#define DINA39 0x39
|
||||
#define DINA41 0x41
|
||||
#define DINA49 0x49
|
||||
#define DINA51 0x51
|
||||
#define DINA59 0x59
|
||||
#define DINA61 0x61
|
||||
#define DINA69 0x69
|
||||
#define DINA71 0x71
|
||||
#define DINA79 0x79
|
||||
|
||||
#define DINA25 0x25
|
||||
#define DINA2D 0x2d
|
||||
#define DINA35 0x35
|
||||
#define DINA3D 0x3d
|
||||
#define DINA4D 0x4d
|
||||
#define DINA55 0x55
|
||||
#define DINA5D 0x5D
|
||||
#define DINA6D 0x6d
|
||||
#define DINA75 0x75
|
||||
#define DINA7D 0x7d
|
||||
|
||||
#define DINADC 0xdc
|
||||
#define DINAF2 0xf2
|
||||
#define DINAAB 0xab
|
||||
#define DINAAA 0xaa
|
||||
#define DINAF1 0xf1
|
||||
#define DINADF 0xdf
|
||||
#define DINADA 0xda
|
||||
#define DINAB1 0xb1
|
||||
#define DINAB9 0xb9
|
||||
#define DINAF3 0xf3
|
||||
#define DINA8B 0x8b
|
||||
#define DINAA3 0xa3
|
||||
#define DINA91 0x91
|
||||
#define DINAB6 0xb6
|
||||
#define DINAB4 0xb4
|
||||
|
||||
|
||||
#define DINC00 0x00
|
||||
#define DINC01 0x01
|
||||
#define DINC02 0x02
|
||||
#define DINC03 0x03
|
||||
#define DINC08 0x08
|
||||
#define DINC09 0x09
|
||||
#define DINC0A 0x0a
|
||||
#define DINC0B 0x0b
|
||||
#define DINC10 0x10
|
||||
#define DINC11 0x11
|
||||
#define DINC12 0x12
|
||||
#define DINC13 0x13
|
||||
#define DINC18 0x18
|
||||
#define DINC19 0x19
|
||||
#define DINC1A 0x1a
|
||||
#define DINC1B 0x1b
|
||||
|
||||
#define DINC20 0x20
|
||||
#define DINC21 0x21
|
||||
#define DINC22 0x22
|
||||
#define DINC23 0x23
|
||||
#define DINC28 0x28
|
||||
#define DINC29 0x29
|
||||
#define DINC2A 0x2a
|
||||
#define DINC2B 0x2b
|
||||
#define DINC30 0x30
|
||||
#define DINC31 0x31
|
||||
#define DINC32 0x32
|
||||
#define DINC33 0x33
|
||||
#define DINC38 0x38
|
||||
#define DINC39 0x39
|
||||
#define DINC3A 0x3a
|
||||
#define DINC3B 0x3b
|
||||
|
||||
#define DINC40 0x40
|
||||
#define DINC41 0x41
|
||||
#define DINC42 0x42
|
||||
#define DINC43 0x43
|
||||
#define DINC48 0x48
|
||||
#define DINC49 0x49
|
||||
#define DINC4A 0x4a
|
||||
#define DINC4B 0x4b
|
||||
#define DINC50 0x50
|
||||
#define DINC51 0x51
|
||||
#define DINC52 0x52
|
||||
#define DINC53 0x53
|
||||
#define DINC58 0x58
|
||||
#define DINC59 0x59
|
||||
#define DINC5A 0x5a
|
||||
#define DINC5B 0x5b
|
||||
|
||||
#define DINC60 0x60
|
||||
#define DINC61 0x61
|
||||
#define DINC62 0x62
|
||||
#define DINC63 0x63
|
||||
#define DINC68 0x68
|
||||
#define DINC69 0x69
|
||||
#define DINC6A 0x6a
|
||||
#define DINC6B 0x6b
|
||||
#define DINC70 0x70
|
||||
#define DINC71 0x71
|
||||
#define DINC72 0x72
|
||||
#define DINC73 0x73
|
||||
#define DINC78 0x78
|
||||
#define DINC79 0x79
|
||||
#define DINC7A 0x7a
|
||||
#define DINC7B 0x7b
|
||||
|
||||
#define DIND40 0x40
|
||||
|
||||
|
||||
#define DINA80 0x80
|
||||
#define DINA90 0x90
|
||||
#define DINAA0 0xa0
|
||||
#define DINAC9 0xc9
|
||||
#define DINACB 0xcb
|
||||
#define DINACD 0xcd
|
||||
#define DINACF 0xcf
|
||||
#define DINAC8 0xc8
|
||||
#define DINACA 0xca
|
||||
#define DINACC 0xcc
|
||||
#define DINACE 0xce
|
||||
#define DINAD8 0xd8
|
||||
#define DINADD 0xdd
|
||||
#define DINAF8 0xf0
|
||||
#define DINAFE 0xfe
|
||||
|
||||
#define DINBF8 0xf8
|
||||
#define DINAC0 0xb0
|
||||
#define DINAC1 0xb1
|
||||
#define DINAC2 0xb4
|
||||
#define DINAC3 0xb5
|
||||
#define DINAC4 0xb8
|
||||
#define DINAC5 0xb9
|
||||
#define DINBC0 0xc0
|
||||
#define DINBC2 0xc2
|
||||
#define DINBC4 0xc4
|
||||
#define DINBC6 0xc6
|
||||
|
||||
|
||||
|
||||
#endif // DMPKEY_H__
|
264
interface/external/MotionDriver/include/dmpmap.h
vendored
Normal file
264
interface/external/MotionDriver/include/dmpmap.h
vendored
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
$License:
|
||||
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
|
||||
$
|
||||
*/
|
||||
#ifndef DMPMAP_H
|
||||
#define DMPMAP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define DMP_PTAT 0
|
||||
#define DMP_XGYR 2
|
||||
#define DMP_YGYR 4
|
||||
#define DMP_ZGYR 6
|
||||
#define DMP_XACC 8
|
||||
#define DMP_YACC 10
|
||||
#define DMP_ZACC 12
|
||||
#define DMP_ADC1 14
|
||||
#define DMP_ADC2 16
|
||||
#define DMP_ADC3 18
|
||||
#define DMP_BIASUNC 20
|
||||
#define DMP_FIFORT 22
|
||||
#define DMP_INVGSFH 24
|
||||
#define DMP_INVGSFL 26
|
||||
#define DMP_1H 28
|
||||
#define DMP_1L 30
|
||||
#define DMP_BLPFSTCH 32
|
||||
#define DMP_BLPFSTCL 34
|
||||
#define DMP_BLPFSXH 36
|
||||
#define DMP_BLPFSXL 38
|
||||
#define DMP_BLPFSYH 40
|
||||
#define DMP_BLPFSYL 42
|
||||
#define DMP_BLPFSZH 44
|
||||
#define DMP_BLPFSZL 46
|
||||
#define DMP_BLPFMTC 48
|
||||
#define DMP_SMC 50
|
||||
#define DMP_BLPFMXH 52
|
||||
#define DMP_BLPFMXL 54
|
||||
#define DMP_BLPFMYH 56
|
||||
#define DMP_BLPFMYL 58
|
||||
#define DMP_BLPFMZH 60
|
||||
#define DMP_BLPFMZL 62
|
||||
#define DMP_BLPFC 64
|
||||
#define DMP_SMCTH 66
|
||||
#define DMP_0H2 68
|
||||
#define DMP_0L2 70
|
||||
#define DMP_BERR2H 72
|
||||
#define DMP_BERR2L 74
|
||||
#define DMP_BERR2NH 76
|
||||
#define DMP_SMCINC 78
|
||||
#define DMP_ANGVBXH 80
|
||||
#define DMP_ANGVBXL 82
|
||||
#define DMP_ANGVBYH 84
|
||||
#define DMP_ANGVBYL 86
|
||||
#define DMP_ANGVBZH 88
|
||||
#define DMP_ANGVBZL 90
|
||||
#define DMP_BERR1H 92
|
||||
#define DMP_BERR1L 94
|
||||
#define DMP_ATCH 96
|
||||
#define DMP_BIASUNCSF 98
|
||||
#define DMP_ACT2H 100
|
||||
#define DMP_ACT2L 102
|
||||
#define DMP_GSFH 104
|
||||
#define DMP_GSFL 106
|
||||
#define DMP_GH 108
|
||||
#define DMP_GL 110
|
||||
#define DMP_0_5H 112
|
||||
#define DMP_0_5L 114
|
||||
#define DMP_0_0H 116
|
||||
#define DMP_0_0L 118
|
||||
#define DMP_1_0H 120
|
||||
#define DMP_1_0L 122
|
||||
#define DMP_1_5H 124
|
||||
#define DMP_1_5L 126
|
||||
#define DMP_TMP1AH 128
|
||||
#define DMP_TMP1AL 130
|
||||
#define DMP_TMP2AH 132
|
||||
#define DMP_TMP2AL 134
|
||||
#define DMP_TMP3AH 136
|
||||
#define DMP_TMP3AL 138
|
||||
#define DMP_TMP4AH 140
|
||||
#define DMP_TMP4AL 142
|
||||
#define DMP_XACCW 144
|
||||
#define DMP_TMP5 146
|
||||
#define DMP_XACCB 148
|
||||
#define DMP_TMP8 150
|
||||
#define DMP_YACCB 152
|
||||
#define DMP_TMP9 154
|
||||
#define DMP_ZACCB 156
|
||||
#define DMP_TMP10 158
|
||||
#define DMP_DZH 160
|
||||
#define DMP_DZL 162
|
||||
#define DMP_XGCH 164
|
||||
#define DMP_XGCL 166
|
||||
#define DMP_YGCH 168
|
||||
#define DMP_YGCL 170
|
||||
#define DMP_ZGCH 172
|
||||
#define DMP_ZGCL 174
|
||||
#define DMP_YACCW 176
|
||||
#define DMP_TMP7 178
|
||||
#define DMP_AFB1H 180
|
||||
#define DMP_AFB1L 182
|
||||
#define DMP_AFB2H 184
|
||||
#define DMP_AFB2L 186
|
||||
#define DMP_MAGFBH 188
|
||||
#define DMP_MAGFBL 190
|
||||
#define DMP_QT1H 192
|
||||
#define DMP_QT1L 194
|
||||
#define DMP_QT2H 196
|
||||
#define DMP_QT2L 198
|
||||
#define DMP_QT3H 200
|
||||
#define DMP_QT3L 202
|
||||
#define DMP_QT4H 204
|
||||
#define DMP_QT4L 206
|
||||
#define DMP_CTRL1H 208
|
||||
#define DMP_CTRL1L 210
|
||||
#define DMP_CTRL2H 212
|
||||
#define DMP_CTRL2L 214
|
||||
#define DMP_CTRL3H 216
|
||||
#define DMP_CTRL3L 218
|
||||
#define DMP_CTRL4H 220
|
||||
#define DMP_CTRL4L 222
|
||||
#define DMP_CTRLS1 224
|
||||
#define DMP_CTRLSF1 226
|
||||
#define DMP_CTRLS2 228
|
||||
#define DMP_CTRLSF2 230
|
||||
#define DMP_CTRLS3 232
|
||||
#define DMP_CTRLSFNLL 234
|
||||
#define DMP_CTRLS4 236
|
||||
#define DMP_CTRLSFNL2 238
|
||||
#define DMP_CTRLSFNL 240
|
||||
#define DMP_TMP30 242
|
||||
#define DMP_CTRLSFJT 244
|
||||
#define DMP_TMP31 246
|
||||
#define DMP_TMP11 248
|
||||
#define DMP_CTRLSF2_2 250
|
||||
#define DMP_TMP12 252
|
||||
#define DMP_CTRLSF1_2 254
|
||||
#define DMP_PREVPTAT 256
|
||||
#define DMP_ACCZB 258
|
||||
#define DMP_ACCXB 264
|
||||
#define DMP_ACCYB 266
|
||||
#define DMP_1HB 272
|
||||
#define DMP_1LB 274
|
||||
#define DMP_0H 276
|
||||
#define DMP_0L 278
|
||||
#define DMP_ASR22H 280
|
||||
#define DMP_ASR22L 282
|
||||
#define DMP_ASR6H 284
|
||||
#define DMP_ASR6L 286
|
||||
#define DMP_TMP13 288
|
||||
#define DMP_TMP14 290
|
||||
#define DMP_FINTXH 292
|
||||
#define DMP_FINTXL 294
|
||||
#define DMP_FINTYH 296
|
||||
#define DMP_FINTYL 298
|
||||
#define DMP_FINTZH 300
|
||||
#define DMP_FINTZL 302
|
||||
#define DMP_TMP1BH 304
|
||||
#define DMP_TMP1BL 306
|
||||
#define DMP_TMP2BH 308
|
||||
#define DMP_TMP2BL 310
|
||||
#define DMP_TMP3BH 312
|
||||
#define DMP_TMP3BL 314
|
||||
#define DMP_TMP4BH 316
|
||||
#define DMP_TMP4BL 318
|
||||
#define DMP_STXG 320
|
||||
#define DMP_ZCTXG 322
|
||||
#define DMP_STYG 324
|
||||
#define DMP_ZCTYG 326
|
||||
#define DMP_STZG 328
|
||||
#define DMP_ZCTZG 330
|
||||
#define DMP_CTRLSFJT2 332
|
||||
#define DMP_CTRLSFJTCNT 334
|
||||
#define DMP_PVXG 336
|
||||
#define DMP_TMP15 338
|
||||
#define DMP_PVYG 340
|
||||
#define DMP_TMP16 342
|
||||
#define DMP_PVZG 344
|
||||
#define DMP_TMP17 346
|
||||
#define DMP_MNMFLAGH 352
|
||||
#define DMP_MNMFLAGL 354
|
||||
#define DMP_MNMTMH 356
|
||||
#define DMP_MNMTML 358
|
||||
#define DMP_MNMTMTHRH 360
|
||||
#define DMP_MNMTMTHRL 362
|
||||
#define DMP_MNMTHRH 364
|
||||
#define DMP_MNMTHRL 366
|
||||
#define DMP_ACCQD4H 368
|
||||
#define DMP_ACCQD4L 370
|
||||
#define DMP_ACCQD5H 372
|
||||
#define DMP_ACCQD5L 374
|
||||
#define DMP_ACCQD6H 376
|
||||
#define DMP_ACCQD6L 378
|
||||
#define DMP_ACCQD7H 380
|
||||
#define DMP_ACCQD7L 382
|
||||
#define DMP_ACCQD0H 384
|
||||
#define DMP_ACCQD0L 386
|
||||
#define DMP_ACCQD1H 388
|
||||
#define DMP_ACCQD1L 390
|
||||
#define DMP_ACCQD2H 392
|
||||
#define DMP_ACCQD2L 394
|
||||
#define DMP_ACCQD3H 396
|
||||
#define DMP_ACCQD3L 398
|
||||
#define DMP_XN2H 400
|
||||
#define DMP_XN2L 402
|
||||
#define DMP_XN1H 404
|
||||
#define DMP_XN1L 406
|
||||
#define DMP_YN2H 408
|
||||
#define DMP_YN2L 410
|
||||
#define DMP_YN1H 412
|
||||
#define DMP_YN1L 414
|
||||
#define DMP_YH 416
|
||||
#define DMP_YL 418
|
||||
#define DMP_B0H 420
|
||||
#define DMP_B0L 422
|
||||
#define DMP_A1H 424
|
||||
#define DMP_A1L 426
|
||||
#define DMP_A2H 428
|
||||
#define DMP_A2L 430
|
||||
#define DMP_SEM1 432
|
||||
#define DMP_FIFOCNT 434
|
||||
#define DMP_SH_TH_X 436
|
||||
#define DMP_PACKET 438
|
||||
#define DMP_SH_TH_Y 440
|
||||
#define DMP_FOOTER 442
|
||||
#define DMP_SH_TH_Z 444
|
||||
#define DMP_TEMP29 448
|
||||
#define DMP_TEMP30 450
|
||||
#define DMP_XACCB_PRE 452
|
||||
#define DMP_XACCB_PREL 454
|
||||
#define DMP_YACCB_PRE 456
|
||||
#define DMP_YACCB_PREL 458
|
||||
#define DMP_ZACCB_PRE 460
|
||||
#define DMP_ZACCB_PREL 462
|
||||
#define DMP_TMP22 464
|
||||
#define DMP_TAP_TIMER 466
|
||||
#define DMP_TAP_THX 468
|
||||
#define DMP_TAP_THY 472
|
||||
#define DMP_TAP_THZ 476
|
||||
#define DMP_TAPW_MIN 478
|
||||
#define DMP_TMP25 480
|
||||
#define DMP_TMP26 482
|
||||
#define DMP_TMP27 484
|
||||
#define DMP_TMP28 486
|
||||
#define DMP_ORIENT 488
|
||||
#define DMP_THRSH 490
|
||||
#define DMP_ENDIANH 492
|
||||
#define DMP_ENDIANL 494
|
||||
#define DMP_BLPFNMTCH 496
|
||||
#define DMP_BLPFNMTCL 498
|
||||
#define DMP_BLPFNMXH 500
|
||||
#define DMP_BLPFNMXL 502
|
||||
#define DMP_BLPFNMYH 504
|
||||
#define DMP_BLPFNMYL 506
|
||||
#define DMP_BLPFNMZH 508
|
||||
#define DMP_BLPFNMZL 510
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // DMPMAP_H
|
127
interface/external/MotionDriver/include/inv_mpu.h
vendored
Normal file
127
interface/external/MotionDriver/include/inv_mpu.h
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
$License:
|
||||
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
|
||||
See included License.txt for License information.
|
||||
$
|
||||
*/
|
||||
/**
|
||||
* @addtogroup DRIVERS Sensor Driver Layer
|
||||
* @brief Hardware drivers to communicate with sensors via I2C.
|
||||
*
|
||||
* @{
|
||||
* @file inv_mpu.h
|
||||
* @brief An I2C-based driver for Invensense gyroscopes.
|
||||
* @details This driver currently works for the following devices:
|
||||
* MPU6050
|
||||
* MPU6500
|
||||
* MPU9150 (or MPU6050 w/ AK8975 on the auxiliary bus)
|
||||
* MPU9250 (or MPU6500 w/ AK8963 on the auxiliary bus)
|
||||
*/
|
||||
|
||||
#ifndef _INV_MPU_H_
|
||||
#define _INV_MPU_H_
|
||||
|
||||
#define INV_X_GYRO (0x40)
|
||||
#define INV_Y_GYRO (0x20)
|
||||
#define INV_Z_GYRO (0x10)
|
||||
#define INV_XYZ_GYRO (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO)
|
||||
#define INV_XYZ_ACCEL (0x08)
|
||||
#define INV_XYZ_COMPASS (0x01)
|
||||
|
||||
struct int_param_s {
|
||||
#if defined EMPL_TARGET_MSP430 || defined MOTION_DRIVER_TARGET_MSP430
|
||||
void (*cb)(void);
|
||||
unsigned short pin;
|
||||
unsigned char lp_exit;
|
||||
unsigned char active_low;
|
||||
#elif defined EMPL_TARGET_UC3L0
|
||||
unsigned long pin;
|
||||
void (*cb)(volatile void*);
|
||||
void *arg;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MPU_INT_STATUS_DATA_READY (0x0001)
|
||||
#define MPU_INT_STATUS_DMP (0x0002)
|
||||
#define MPU_INT_STATUS_PLL_READY (0x0004)
|
||||
#define MPU_INT_STATUS_I2C_MST (0x0008)
|
||||
#define MPU_INT_STATUS_FIFO_OVERFLOW (0x0010)
|
||||
#define MPU_INT_STATUS_ZMOT (0x0020)
|
||||
#define MPU_INT_STATUS_MOT (0x0040)
|
||||
#define MPU_INT_STATUS_FREE_FALL (0x0080)
|
||||
#define MPU_INT_STATUS_DMP_0 (0x0100)
|
||||
#define MPU_INT_STATUS_DMP_1 (0x0200)
|
||||
#define MPU_INT_STATUS_DMP_2 (0x0400)
|
||||
#define MPU_INT_STATUS_DMP_3 (0x0800)
|
||||
#define MPU_INT_STATUS_DMP_4 (0x1000)
|
||||
#define MPU_INT_STATUS_DMP_5 (0x2000)
|
||||
|
||||
/* Set up APIs */
|
||||
int mpu_init(struct int_param_s *int_param);
|
||||
int mpu_init_slave(void);
|
||||
int mpu_set_bypass(unsigned char bypass_on);
|
||||
|
||||
/* Configuration APIs */
|
||||
int mpu_lp_accel_mode(unsigned char rate);
|
||||
int mpu_lp_motion_interrupt(unsigned short thresh, unsigned char time,
|
||||
unsigned char lpa_freq);
|
||||
int mpu_set_int_level(unsigned char active_low);
|
||||
int mpu_set_int_latched(unsigned char enable);
|
||||
|
||||
int mpu_set_dmp_state(unsigned char enable);
|
||||
int mpu_get_dmp_state(unsigned char *enabled);
|
||||
|
||||
int mpu_get_lpf(unsigned short *lpf);
|
||||
int mpu_set_lpf(unsigned short lpf);
|
||||
|
||||
int mpu_get_gyro_fsr(unsigned short *fsr);
|
||||
int mpu_set_gyro_fsr(unsigned short fsr);
|
||||
|
||||
int mpu_get_accel_fsr(unsigned char *fsr);
|
||||
int mpu_set_accel_fsr(unsigned char fsr);
|
||||
|
||||
int mpu_get_compass_fsr(unsigned short *fsr);
|
||||
|
||||
int mpu_get_gyro_sens(float *sens);
|
||||
int mpu_get_accel_sens(unsigned short *sens);
|
||||
|
||||
int mpu_get_sample_rate(unsigned short *rate);
|
||||
int mpu_set_sample_rate(unsigned short rate);
|
||||
int mpu_get_compass_sample_rate(unsigned short *rate);
|
||||
int mpu_set_compass_sample_rate(unsigned short rate);
|
||||
|
||||
int mpu_get_fifo_config(unsigned char *sensors);
|
||||
int mpu_configure_fifo(unsigned char sensors);
|
||||
|
||||
int mpu_get_power_state(unsigned char *power_on);
|
||||
int mpu_set_sensors(unsigned char sensors);
|
||||
|
||||
int mpu_set_accel_bias(const long *accel_bias);
|
||||
|
||||
/* Data getter/setter APIs */
|
||||
int mpu_get_gyro_reg(short *data, unsigned long *timestamp);
|
||||
int mpu_get_accel_reg(short *data, unsigned long *timestamp);
|
||||
int mpu_get_compass_reg(short *data, unsigned long *timestamp);
|
||||
int mpu_get_temperature(long *data, unsigned long *timestamp);
|
||||
|
||||
int mpu_get_int_status(short *status);
|
||||
int mpu_read_fifo(short *gyro, short *accel, unsigned long *timestamp,
|
||||
unsigned char *sensors, unsigned char *more);
|
||||
int mpu_read_fifo_stream(unsigned short length, unsigned char *data,
|
||||
unsigned char *more);
|
||||
int mpu_reset_fifo(void);
|
||||
|
||||
int mpu_write_mem(unsigned short mem_addr, unsigned short length,
|
||||
unsigned char *data);
|
||||
int mpu_read_mem(unsigned short mem_addr, unsigned short length,
|
||||
unsigned char *data);
|
||||
int mpu_load_firmware(unsigned short length, const unsigned char *firmware,
|
||||
unsigned short start_addr, unsigned short sample_rate);
|
||||
|
||||
int mpu_reg_dump(void);
|
||||
int mpu_read_reg(unsigned char reg, unsigned char *data);
|
||||
int mpu_run_self_test(long *gyro, long *accel);
|
||||
int mpu_register_tap_cb(void (*func)(unsigned char, unsigned char));
|
||||
|
||||
#endif /* #ifndef _INV_MPU_H_ */
|
||||
|
97
interface/external/MotionDriver/include/inv_mpu_dmp_motion_driver.h
vendored
Normal file
97
interface/external/MotionDriver/include/inv_mpu_dmp_motion_driver.h
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
$License:
|
||||
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
|
||||
See included License.txt for License information.
|
||||
$
|
||||
*/
|
||||
/**
|
||||
* @addtogroup DRIVERS Sensor Driver Layer
|
||||
* @brief Hardware drivers to communicate with sensors via I2C.
|
||||
*
|
||||
* @{
|
||||
* @file inv_mpu_dmp_motion_driver.h
|
||||
* @brief DMP image and interface functions.
|
||||
* @details All functions are preceded by the dmp_ prefix to
|
||||
* differentiate among MPL and general driver function calls.
|
||||
*/
|
||||
#ifndef _INV_MPU_DMP_MOTION_DRIVER_H_
|
||||
#define _INV_MPU_DMP_MOTION_DRIVER_H_
|
||||
|
||||
#define TAP_X (0x01)
|
||||
#define TAP_Y (0x02)
|
||||
#define TAP_Z (0x04)
|
||||
#define TAP_XYZ (0x07)
|
||||
|
||||
#define TAP_X_UP (0x01)
|
||||
#define TAP_X_DOWN (0x02)
|
||||
#define TAP_Y_UP (0x03)
|
||||
#define TAP_Y_DOWN (0x04)
|
||||
#define TAP_Z_UP (0x05)
|
||||
#define TAP_Z_DOWN (0x06)
|
||||
|
||||
#define ANDROID_ORIENT_PORTRAIT (0x00)
|
||||
#define ANDROID_ORIENT_LANDSCAPE (0x01)
|
||||
#define ANDROID_ORIENT_REVERSE_PORTRAIT (0x02)
|
||||
#define ANDROID_ORIENT_REVERSE_LANDSCAPE (0x03)
|
||||
|
||||
#define DMP_INT_GESTURE (0x01)
|
||||
#define DMP_INT_CONTINUOUS (0x02)
|
||||
|
||||
#define DMP_FEATURE_TAP (0x001)
|
||||
#define DMP_FEATURE_ANDROID_ORIENT (0x002)
|
||||
#define DMP_FEATURE_LP_QUAT (0x004)
|
||||
#define DMP_FEATURE_PEDOMETER (0x008)
|
||||
#define DMP_FEATURE_6X_LP_QUAT (0x010)
|
||||
#define DMP_FEATURE_GYRO_CAL (0x020)
|
||||
#define DMP_FEATURE_SEND_RAW_ACCEL (0x040)
|
||||
#define DMP_FEATURE_SEND_RAW_GYRO (0x080)
|
||||
#define DMP_FEATURE_SEND_CAL_GYRO (0x100)
|
||||
|
||||
#define INV_WXYZ_QUAT (0x100)
|
||||
|
||||
/* Set up functions. */
|
||||
int dmp_load_motion_driver_firmware(void);
|
||||
int dmp_set_fifo_rate(unsigned short rate);
|
||||
int dmp_get_fifo_rate(unsigned short *rate);
|
||||
int dmp_enable_feature(unsigned short mask);
|
||||
int dmp_get_enabled_features(unsigned short *mask);
|
||||
int dmp_set_interrupt_mode(unsigned char mode);
|
||||
int dmp_set_orientation(unsigned short orient);
|
||||
int dmp_set_gyro_bias(long *bias);
|
||||
int dmp_set_accel_bias(long *bias);
|
||||
|
||||
/* Tap functions. */
|
||||
int dmp_register_tap_cb(void (*func)(unsigned char, unsigned char));
|
||||
int dmp_set_tap_thresh(unsigned char axis, unsigned short thresh);
|
||||
int dmp_set_tap_axes(unsigned char axis);
|
||||
int dmp_set_tap_count(unsigned char min_taps);
|
||||
int dmp_set_tap_time(unsigned short time);
|
||||
int dmp_set_tap_time_multi(unsigned short time);
|
||||
int dmp_set_shake_reject_thresh(long sf, unsigned short thresh);
|
||||
int dmp_set_shake_reject_time(unsigned short time);
|
||||
int dmp_set_shake_reject_timeout(unsigned short time);
|
||||
|
||||
/* Android orientation functions. */
|
||||
int dmp_register_android_orient_cb(void (*func)(unsigned char));
|
||||
|
||||
/* LP quaternion functions. */
|
||||
int dmp_enable_lp_quat(unsigned char enable);
|
||||
int dmp_enable_6x_lp_quat(unsigned char enable);
|
||||
|
||||
/* Pedometer functions. */
|
||||
int dmp_get_pedometer_step_count(unsigned long *count);
|
||||
int dmp_set_pedometer_step_count(unsigned long count);
|
||||
int dmp_get_pedometer_walk_time(unsigned long *time);
|
||||
int dmp_set_pedometer_walk_time(unsigned long time);
|
||||
|
||||
/* DMP gyro calibration functions. */
|
||||
int dmp_enable_gyro_cal(unsigned char enable);
|
||||
|
||||
/* Read function. This function should be called whenever the MPU interrupt is
|
||||
* detected.
|
||||
*/
|
||||
int dmp_read_fifo(short *gyro, short *accel, long *quat,
|
||||
unsigned long *timestamp, short *sensors, unsigned char *more);
|
||||
|
||||
#endif /* #ifndef _INV_MPU_DMP_MOTION_DRIVER_H_ */
|
||||
|
22
interface/external/MotionDriver/include/inv_tty.h
vendored
Normal file
22
interface/external/MotionDriver/include/inv_tty.h
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// inv_tty.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/9/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__inv_tty__
|
||||
#define __interface__inv_tty__
|
||||
|
||||
void tty_set_file_descriptor(int file_descriptor);
|
||||
|
||||
int tty_i2c_write(unsigned char slave_addr, unsigned char reg_addr, unsigned char length, unsigned char const *data);
|
||||
|
||||
int tty_i2c_read(unsigned char slave_addr, unsigned char reg_addr, unsigned char length, unsigned char *data);
|
||||
|
||||
void tty_delay_ms(unsigned long num_ms);
|
||||
|
||||
void tty_get_ms(unsigned long *count);
|
||||
|
||||
#endif /* defined(__interface__inv_tty__) */
|
BIN
interface/external/MotionDriver/lib/MacOS/libMotionDriver.a
vendored
Normal file
BIN
interface/external/MotionDriver/lib/MacOS/libMotionDriver.a
vendored
Normal file
Binary file not shown.
BIN
interface/external/MotionDriver/lib/UNIX/libMotionDriver.a
vendored
Normal file
BIN
interface/external/MotionDriver/lib/UNIX/libMotionDriver.a
vendored
Normal file
Binary file not shown.
2798
interface/external/MotionDriver/src/inv_mpu.c
vendored
Normal file
2798
interface/external/MotionDriver/src/inv_mpu.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1373
interface/external/MotionDriver/src/inv_mpu_dmp_motion_driver.c
vendored
Normal file
1373
interface/external/MotionDriver/src/inv_mpu_dmp_motion_driver.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
90
interface/external/MotionDriver/src/inv_tty.c
vendored
Normal file
90
interface/external/MotionDriver/src/inv_tty.c
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// inv_tty.c
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/9/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "inv_tty.h"
|
||||
|
||||
// the file descriptor of the tty
|
||||
static int ttyFileDescriptor;
|
||||
|
||||
void tty_set_file_descriptor(int file_descriptor) {
|
||||
ttyFileDescriptor = file_descriptor;
|
||||
}
|
||||
|
||||
static char to_hex_digit(unsigned char value) {
|
||||
return (value < 10) ? '0' + value : 'A' + (value - 10);
|
||||
}
|
||||
|
||||
static unsigned char from_hex_digit(char digit) {
|
||||
return (digit < 'A') ? digit - '0' : (digit - 'A') + 10;
|
||||
}
|
||||
|
||||
static void write_byte(unsigned char value) {
|
||||
char chars[] = { to_hex_digit(value / 16), to_hex_digit(value % 16) };
|
||||
write(ttyFileDescriptor, chars, 2);
|
||||
}
|
||||
|
||||
static unsigned char read_byte() {
|
||||
char chars[2];
|
||||
read(ttyFileDescriptor, chars, 2);
|
||||
return from_hex_digit(chars[0]) * 16 + from_hex_digit(chars[1]);
|
||||
}
|
||||
|
||||
int tty_i2c_write(unsigned char slave_addr, unsigned char reg_addr, unsigned char length, unsigned char const *data) {
|
||||
write(ttyFileDescriptor, "WR", 2);
|
||||
write_byte(slave_addr);
|
||||
write_byte(reg_addr);
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
write_byte(data[i]);
|
||||
}
|
||||
write(ttyFileDescriptor, "\n", 1);
|
||||
|
||||
char response[8];
|
||||
read(ttyFileDescriptor, response, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tty_i2c_read(unsigned char slave_addr, unsigned char reg_addr, unsigned char length, unsigned char *data) {
|
||||
write(ttyFileDescriptor, "RD", 2);
|
||||
write_byte(slave_addr);
|
||||
write_byte(reg_addr);
|
||||
write_byte(length);
|
||||
write(ttyFileDescriptor, "\n", 1);
|
||||
|
||||
char prefix[6];
|
||||
read(ttyFileDescriptor, prefix, 6);
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
data[i] = read_byte();
|
||||
}
|
||||
|
||||
char suffix[2];
|
||||
read(ttyFileDescriptor, suffix, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tty_delay_ms(unsigned long num_ms) {
|
||||
struct timespec required, remaining;
|
||||
required.tv_sec = 0;
|
||||
const long NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
required.tv_nsec = num_ms * NANOSECONDS_PER_MILLISECOND;
|
||||
nanosleep(&required, &remaining);
|
||||
}
|
||||
|
||||
void tty_get_ms(unsigned long *count) {
|
||||
struct timeval time;
|
||||
gettimeofday(&time, 0);
|
||||
const long MILLISECONDS_PER_SECOND = 1000;
|
||||
const long MICROSECONDS_PER_MILLISECOND = 1000;
|
||||
*count = time.tv_sec * MILLISECONDS_PER_SECOND + time.tv_usec / MICROSECONDS_PER_MILLISECOND;
|
||||
}
|
177
interface/resources/images/hifi-interface-tools.svg
Normal file
177
interface/resources/images/hifi-interface-tools.svg
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="124px" height="400px" viewBox="-0.5 0.5 124 400" enable-background="new -0.5 0.5 124 400" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="-0.5" y="120.382" width="62" height="40"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#999999" d="M13.77,149.864c0.296,0.296,0.665,0.102,0.665,0.102s0.527-0.615,1.101-0.328
|
||||
c0.811,0.405,1.315-0.113,1.315-0.113l10.611-10.611l-1.419-1.419l-1.161-1.161l-10.61,10.61c0,0-0.575,0.449-0.169,1.261
|
||||
c0.287,0.573-0.384,1.045-0.384,1.045S13.474,149.569,13.77,149.864"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#CCCCCC" d="M25.913,135.042l2.173-2.173c0,0,1.898-1.905,3.256-0.547c0.68,0.68,1.083,1.627-0.546,3.257
|
||||
c-1.549,1.548-2.173,2.172-2.173,2.172L25.913,135.042z"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="22.984" y="135.651" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 -52.0828 253.0143)" fill="#CCCCCC" width="6.751" height="3.285"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M46.482,138.915h3.697v4.617c-1.004,0.344-2.107,0.516-3.311,0.516c-1.32,0-2.341-0.383-3.062-1.148
|
||||
s-1.081-1.857-1.081-3.275c0-1.383,0.395-2.459,1.184-3.229s1.895-1.154,3.316-1.154c0.539,0,1.048,0.051,1.526,0.152
|
||||
s0.896,0.23,1.251,0.387l-0.732,1.816c-0.617-0.305-1.295-0.457-2.033-0.457c-0.676,0-1.198,0.22-1.567,0.659
|
||||
s-0.554,1.067-0.554,1.884c0,0.801,0.167,1.411,0.501,1.831s0.815,0.63,1.444,0.63c0.344,0,0.66-0.033,0.949-0.1v-1.342h-1.529
|
||||
L46.482,138.915L46.482,138.915z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="-0.5" y="80.5" width="62" height="40"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M43.84,96.434h2.988c1.164,0,2.028,0.173,2.593,0.519s0.847,0.884,0.847,1.614
|
||||
c0,0.48-0.123,0.891-0.369,1.23s-0.57,0.559-0.973,0.656v0.059c0.531,0.141,0.916,0.375,1.154,0.703s0.357,0.754,0.357,1.277
|
||||
c0,0.777-0.292,1.39-0.876,1.837S48.182,105,47.174,105H43.84V96.434z M46.154,99.721h0.697c0.332,0,0.589-0.068,0.771-0.205
|
||||
s0.272-0.34,0.272-0.609c0-0.48-0.363-0.721-1.09-0.721h-0.65C46.154,98.186,46.154,99.721,46.154,99.721z M46.154,101.414v1.799
|
||||
h0.814c0.723,0,1.084-0.305,1.084-0.914c0-0.285-0.097-0.504-0.29-0.656s-0.474-0.229-0.841-0.229
|
||||
C46.921,101.414,46.154,101.414,46.154,101.414z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M18,106.06c-3,1-3,3-7,3c2,1,8,4,9,0C20.47,107.181,18,106.06,18,106.06z"/>
|
||||
<path fill="#CCCCCC" d="M19,105.06l2,2c0,0,3.952-4.712,7-9c3.048-4.287,7.32-10.785,3-7C28.399,93.338,22.048,100.772,19,105.06z
|
||||
"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="-0.5" y="40.5" width="62" height="40"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#A5A5A5" points="26,58.63 39,53.893 39,67.213 26,72.394 "/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#333333" d="M38,54.5v12.59l-12,5.032V58.757l12.204-4.468 M39,53.63l-13,4.873v14.162l13-5.33V53.63L39,53.63z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#BFBFBF" points="13,67.213 13,53.893 25,58.63 25,72.394 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#BFBFBF" d="M12.887,54.289L25,58.757v13.365L13,67.09V54.5 M13,53.63v13.705l13,5.33V58.503L13,53.63L13,53.63z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#FFFFFF" points="13.173,53.63 25.746,48.952 38.318,53.63 25.746,58.309 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#333333" d="M25.746,49.146l12.049,4.483l-12.049,4.483L13.697,53.63L25.746,49.146 M25.746,48.758L12.65,53.63
|
||||
l13.096,4.873l13.096-4.873L25.746,48.758L25.746,48.758z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M46.119,62.383V65.5h-2.314v-8.566h2.807c2.328,0,3.492,0.844,3.492,2.531c0,0.992-0.484,1.76-1.453,2.303
|
||||
l2.495,3.732h-2.625l-1.816-3.117H46.119z M46.119,60.643h0.434c0.809,0,1.213-0.357,1.213-1.072c0-0.59-0.396-0.885-1.189-0.885
|
||||
H46.12L46.119,60.643L46.119,60.643z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#333333" points="7,59.5 9,59.5 10,59.5 15,59.5 16,59.5 18,59.5 18,64.5 16,64.5 15,64.5 10,64.5 9,64.5 7,64.5
|
||||
"/>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="8" y="60.5" fill="#FFFFFF" width="9" height="3"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="-0.5" y="0.5" width="62" height="40"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#A5A5A5" points="26,18.63 39,13.893 39,27.213 26,32.394 "/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#333333" d="M38,14.5v12.59l-12,5.032V18.757l12.204-4.468 M39,13.63l-13,4.873v14.162l13-5.33V13.63L39,13.63z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#BFBFBF" points="13,27.213 13,13.893 25,18.63 25,32.394 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#BFBFBF" d="M12.887,14.289L25,18.757v13.365L13,27.09V14.5 M13,13.63v13.705l13,5.33V18.503L13,13.63L13,13.63z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#FFFFFF" points="13.173,13.63 25.746,8.952 38.318,13.63 25.746,18.309 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#333333" d="M25.746,9.146l12.049,4.483l-12.049,4.483L13.697,13.63L25.746,9.146 M25.746,8.758L12.65,13.63
|
||||
l13.096,4.873l13.096-4.873L25.746,8.758L25.746,8.758z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M48.41,16.934H51L48.193,25.5h-2.725l-2.795-8.566h2.602l1.166,4.342c0.242,0.965,0.375,1.637,0.398,2.016
|
||||
c0.027-0.273,0.082-0.615,0.164-1.025s0.154-0.732,0.217-0.967L48.41,16.934z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#333333" points="7,19.5 10,19.5 10,16.5 15,16.5 15,19.5 18,19.5 18,24.5 15,24.5 15,27.5 10,27.5 10,24.5 7,24.5
|
||||
"/>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="11" y="17.5" fill="#FFFFFF" width="3" height="9"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="8" y="20.5" fill="#FFFFFF" width="9" height="3"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="-0.5" y="160.5" width="62" height="40"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M50.379,179.205c0,1.441-0.354,2.537-1.061,3.287s-1.742,1.125-3.105,1.125
|
||||
c-1.344,0-2.374-0.377-3.091-1.131s-1.075-1.852-1.075-3.293c0-1.426,0.356-2.515,1.069-3.267s1.749-1.128,3.108-1.128
|
||||
c1.363,0,2.396,0.373,3.1,1.119S50.379,177.76,50.379,179.205z M44.484,179.205c0,1.656,0.576,2.484,1.729,2.484
|
||||
c0.586,0,1.021-0.201,1.304-0.604s0.425-1.029,0.425-1.881c0-0.855-0.144-1.487-0.431-1.896s-0.716-0.612-1.286-0.612
|
||||
C45.064,176.697,44.484,177.533,44.484,179.205z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" points="19.944,187.389 19.944,188.389 19.031,187.981 "/>
|
||||
|
||||
<line fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="1.9973,1.9973" x1="17.208" y1="187.166" x2="10.825" y2="184.315"/>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" points="9.913,183.908 9,183.5 9,182.5 "/>
|
||||
<line fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="2,2" x1="8.5" y1="180.5" x2="8.5" y2="173.5"/>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" points="9,172.5 9,171.5 9.927,171.876 "/>
|
||||
|
||||
<line fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="1.9625,1.9625" x1="11.745" y1="172.615" x2="18.109" y2="175.199"/>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" points="19.018,175.568 19.944,175.944 19.944,176.944 "/>
|
||||
<line fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="2,2" x1="19.5" y1="179.5" x2="19.5" y2="186.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="2,2" points="19.944,175.944 30,171.5 20,168.5
|
||||
9,171.5 "/>
|
||||
<polyline fill="none" stroke="#CCCCCC" stroke-miterlimit="10" stroke-dasharray="2,2" points="20.333,188.611 29.5,183.5
|
||||
29.5,171.5 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.5 KiB |
|
@ -8,6 +8,7 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
|
@ -63,6 +64,7 @@
|
|||
#include "Util.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
#include "Swatch.h"
|
||||
#include "fvupdater.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -198,7 +200,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_packetCount(0),
|
||||
_packetsPerSecond(0),
|
||||
_bytesPerSecond(0),
|
||||
_bytesCount(0)
|
||||
_bytesCount(0),
|
||||
_swatch(NULL)
|
||||
{
|
||||
_applicationStartupTime = startup_time;
|
||||
_window->setWindowTitle("Interface");
|
||||
|
@ -273,7 +276,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
FvUpdater::sharedUpdater()->SetFeedURL("https://s3-us-west-1.amazonaws.com/highfidelity/appcast.xml");
|
||||
FvUpdater::sharedUpdater()->CheckForUpdatesSilent();
|
||||
#endif
|
||||
|
||||
|
||||
initMenu();
|
||||
|
||||
QRect available = desktop()->availableGeometry();
|
||||
|
@ -337,6 +340,7 @@ void Application::initializeGL() {
|
|||
QTimer* idleTimer = new QTimer(this);
|
||||
connect(idleTimer, SIGNAL(timeout()), SLOT(idle()));
|
||||
idleTimer->start(0);
|
||||
_idleLoopStdev.reset();
|
||||
|
||||
if (_justStarted) {
|
||||
float startupTime = (usecTimestampNow() - usecTimestamp(&_applicationStartupTime)) / 1000000.0;
|
||||
|
@ -726,7 +730,16 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
deleteVoxelUnderCursor();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_1:
|
||||
case Qt::Key_2:
|
||||
case Qt::Key_3:
|
||||
case Qt::Key_4:
|
||||
case Qt::Key_5:
|
||||
case Qt::Key_6:
|
||||
case Qt::Key_7:
|
||||
case Qt::Key_8:
|
||||
_swatch.handleEvent(event->key(), _eyedropperMode->isChecked());
|
||||
break;
|
||||
default:
|
||||
event->ignore();
|
||||
break;
|
||||
|
@ -865,6 +878,8 @@ void Application::touchUpdateEvent(QTouchEvent* event) {
|
|||
|
||||
void Application::touchBeginEvent(QTouchEvent* event) {
|
||||
touchUpdateEvent(event);
|
||||
_lastTouchAvgX = _touchAvgX;
|
||||
_lastTouchAvgY = _touchAvgY;
|
||||
}
|
||||
|
||||
void Application::touchEndEvent(QTouchEvent* event) {
|
||||
|
@ -890,8 +905,9 @@ void Application::wheelEvent(QWheelEvent* event) {
|
|||
void Application::sendPingPackets() {
|
||||
|
||||
char nodeTypesOfInterest[] = {NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER};
|
||||
long long currentTime = usecTimestampNow();
|
||||
unsigned char pingPacket[MAX_PACKET_HEADER_BYTES + sizeof(currentTime)];
|
||||
|
||||
uint64_t currentTime = usecTimestampNow();
|
||||
unsigned char pingPacket[numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_PING) + sizeof(currentTime)];
|
||||
int numHeaderBytes = populateTypeAndVersion(pingPacket, PACKET_TYPE_PING);
|
||||
|
||||
memcpy(&pingPacket[1], ¤tTime, sizeof(currentTime));
|
||||
|
@ -948,25 +964,36 @@ static glm::vec3 getFaceVector(BoxFace face) {
|
|||
}
|
||||
|
||||
void Application::idle() {
|
||||
|
||||
timeval check;
|
||||
gettimeofday(&check, NULL);
|
||||
|
||||
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
||||
|
||||
if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
||||
// We call processEvents() here because the idle timer takes priority over
|
||||
// event handling in Qt, so when the framerate gets low events will pile up
|
||||
// unless we handle them here.
|
||||
|
||||
// NOTE - this is commented out for now - causing event processing issues reported by Philip and Ryan
|
||||
// birarda - July 3rd
|
||||
|
||||
// processEvents();
|
||||
|
||||
update(1.0f / _fps);
|
||||
|
||||
double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check);
|
||||
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
||||
|
||||
// If we're using multi-touch look, immediately process any
|
||||
// touch events, and no other events.
|
||||
// This is necessary because id the idle() call takes longer than the
|
||||
// interval between idle() calls, the event loop never gets to run,
|
||||
// and touch events get delayed.
|
||||
sendPostedEvents(NULL, QEvent::TouchBegin);
|
||||
sendPostedEvents(NULL, QEvent::TouchUpdate);
|
||||
sendPostedEvents(NULL, QEvent::TouchEnd);
|
||||
|
||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||
_glWidget->updateGL();
|
||||
_lastTimeIdle = check;
|
||||
_lastTimeUpdated = check;
|
||||
_idleLoopStdev.addValue(timeSinceLastUpdate);
|
||||
|
||||
// Record standard deviation and reset counter if needed
|
||||
const int STDEV_SAMPLES = 500;
|
||||
if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) {
|
||||
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
||||
_idleLoopStdev.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
void Application::terminate() {
|
||||
|
@ -1197,6 +1224,10 @@ void Application::doFalseColorizeOccluded() {
|
|||
_voxels.falseColorizeOccluded();
|
||||
}
|
||||
|
||||
void Application::doFalseColorizeOccludedV2() {
|
||||
_voxels.falseColorizeOccludedV2();
|
||||
}
|
||||
|
||||
void Application::doTrueVoxelColors() {
|
||||
_voxels.trueColorize();
|
||||
}
|
||||
|
@ -1209,16 +1240,12 @@ void Application::setWantsMonochrome(bool wantsMonochrome) {
|
|||
_myAvatar.setWantColor(!wantsMonochrome);
|
||||
}
|
||||
|
||||
void Application::setWantsResIn(bool wantsResIn) {
|
||||
_myAvatar.setWantResIn(wantsResIn);
|
||||
}
|
||||
|
||||
void Application::setWantsDelta(bool wantsDelta) {
|
||||
_myAvatar.setWantDelta(wantsDelta);
|
||||
}
|
||||
|
||||
void Application::setWantsOcclusionCulling(bool wantsOcclusionCulling) {
|
||||
_myAvatar.setWantOcclusionCulling(wantsOcclusionCulling);
|
||||
void Application::disableOcclusionCulling(bool disableOcclusionCulling) {
|
||||
_myAvatar.setWantOcclusionCulling(!disableOcclusionCulling);
|
||||
}
|
||||
|
||||
void Application::updateVoxelModeActions() {
|
||||
|
@ -1253,7 +1280,11 @@ void Application::decreaseVoxelSize() {
|
|||
void Application::increaseVoxelSize() {
|
||||
_mouseVoxelScale *= 2;
|
||||
}
|
||||
|
||||
|
||||
void Application::resetSwatchColors() {
|
||||
_swatch.reset();
|
||||
}
|
||||
|
||||
static QIcon createSwatchIcon(const QColor& color) {
|
||||
QPixmap map(16, 16);
|
||||
map.fill(color);
|
||||
|
@ -1349,8 +1380,10 @@ void Application::exportVoxels() {
|
|||
|
||||
void Application::importVoxels() {
|
||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
|
||||
tr("Sparse Voxel Octree Files, Square PNG (*.svo *.png)"));
|
||||
QString fileNameString = QFileDialog::getOpenFileName(
|
||||
_glWidget, tr("Import Voxels"), desktopLocation,
|
||||
tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)"));
|
||||
|
||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
|
||||
|
@ -1371,8 +1404,10 @@ void Application::importVoxels() {
|
|||
}
|
||||
|
||||
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height());
|
||||
} else {
|
||||
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
|
||||
importVoxels.readFromSVOFile(fileName);
|
||||
} else {
|
||||
importVoxels.readFromSchematicFile(fileName);
|
||||
}
|
||||
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
|
@ -1482,10 +1517,6 @@ void Application::initMenu() {
|
|||
optionsMenu->addAction("Noise", this, SLOT(setNoise(bool)), Qt::Key_N)->setCheckable(true);
|
||||
(_gyroLook = optionsMenu->addAction("Smooth Gyro Look"))->setCheckable(true);
|
||||
_gyroLook->setChecked(true);
|
||||
(_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true);
|
||||
_mouseLook->setChecked(true);
|
||||
(_touchLook = optionsMenu->addAction("Touch Look"))->setCheckable(true);
|
||||
_touchLook->setChecked(false);
|
||||
(_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true);
|
||||
_showHeadMouse->setChecked(false);
|
||||
(_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true);
|
||||
|
@ -1496,12 +1527,13 @@ void Application::initMenu() {
|
|||
(_testPing = optionsMenu->addAction("Test Ping"))->setCheckable(true);
|
||||
_testPing->setChecked(true);
|
||||
(_fullScreenMode = optionsMenu->addAction("Fullscreen", this, SLOT(setFullscreen(bool)), Qt::Key_F))->setCheckable(true);
|
||||
optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true);
|
||||
optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true);
|
||||
optionsMenu->addAction("Go Home", this, SLOT(goHome()));
|
||||
|
||||
QMenu* renderMenu = menuBar->addMenu("Render");
|
||||
(_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true);
|
||||
_renderVoxels->setChecked(true);
|
||||
_renderVoxels->setShortcut(Qt::Key_V);
|
||||
_renderVoxels->setShortcut(Qt::SHIFT | Qt::Key_V);
|
||||
(_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true);
|
||||
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
|
||||
_renderStarsOn->setChecked(true);
|
||||
|
@ -1543,36 +1575,39 @@ void Application::initMenu() {
|
|||
_voxelModeActions->setExclusive(false); // exclusivity implies one is always checked
|
||||
|
||||
(_addVoxelMode = voxelMenu->addAction(
|
||||
"Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_A))->setCheckable(true);
|
||||
"Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_V))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_addVoxelMode);
|
||||
(_deleteVoxelMode = voxelMenu->addAction(
|
||||
"Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_D))->setCheckable(true);
|
||||
"Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_R))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_deleteVoxelMode);
|
||||
(_colorVoxelMode = voxelMenu->addAction(
|
||||
"Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_B))->setCheckable(true);
|
||||
"Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_B))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_colorVoxelMode);
|
||||
(_selectVoxelMode = voxelMenu->addAction(
|
||||
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true);
|
||||
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_O))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_selectVoxelMode);
|
||||
(_eyedropperMode = voxelMenu->addAction(
|
||||
"Get Color Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_G))->setCheckable(true);
|
||||
"Get Color Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_G))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_eyedropperMode);
|
||||
|
||||
|
||||
voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut);
|
||||
voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), QKeySequence::ZoomIn);
|
||||
|
||||
voxelMenu->addAction("Reset Swatch Colors", this, SLOT(resetSwatchColors()));
|
||||
|
||||
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this,
|
||||
SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C);
|
||||
_swatch.setAction(_voxelPaintColor);
|
||||
|
||||
QColor paintColor(128, 128, 128);
|
||||
_voxelPaintColor->setData(paintColor);
|
||||
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
|
||||
(_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true);
|
||||
|
||||
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
|
||||
voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
|
||||
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
|
||||
voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
|
||||
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
|
||||
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
|
||||
voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
|
||||
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
|
||||
voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
|
||||
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
|
||||
|
||||
QMenu* debugMenu = menuBar->addMenu("Debug");
|
||||
|
||||
|
@ -1597,13 +1632,20 @@ void Application::initMenu() {
|
|||
renderDebugMenu->addAction("FALSE Color Voxels by Distance", this, SLOT(doFalseColorizeByDistance()));
|
||||
renderDebugMenu->addAction("FALSE Color Voxel Out of View", this, SLOT(doFalseColorizeInView()));
|
||||
renderDebugMenu->addAction("FALSE Color Occluded Voxels", this, SLOT(doFalseColorizeOccluded()), Qt::CTRL | Qt::Key_O);
|
||||
renderDebugMenu->addAction("FALSE Color Occluded V2 Voxels", this, SLOT(doFalseColorizeOccludedV2()), Qt::CTRL | Qt::Key_P);
|
||||
renderDebugMenu->addAction("Show TRUE Colors", this, SLOT(doTrueVoxelColors()), Qt::CTRL | Qt::Key_T);
|
||||
|
||||
debugMenu->addAction("Wants Res-In", this, SLOT(setWantsResIn(bool)))->setCheckable(true);
|
||||
debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true);
|
||||
debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true);
|
||||
(_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true);
|
||||
debugMenu->addAction("Wants Occlusion Culling", this, SLOT(setWantsOcclusionCulling(bool)))->setCheckable(true);
|
||||
debugMenu->addAction("Disable Occlusion Culling", this, SLOT(disableOcclusionCulling(bool)),
|
||||
Qt::SHIFT | Qt::Key_C)->setCheckable(true);
|
||||
|
||||
(_renderCoverageMap = debugMenu->addAction("Render Coverage Map"))->setCheckable(true);
|
||||
_renderCoverageMap->setShortcut(Qt::SHIFT | Qt::CTRL | Qt::Key_O);
|
||||
(_renderCoverageMapV2 = debugMenu->addAction("Render Coverage Map V2"))->setCheckable(true);
|
||||
_renderCoverageMapV2->setShortcut(Qt::SHIFT | Qt::CTRL | Qt::Key_P);
|
||||
|
||||
|
||||
QMenu* settingsMenu = menuBar->addMenu("Settings");
|
||||
(_settingsAutosave = settingsMenu->addAction("Autosave"))->setCheckable(true);
|
||||
|
@ -1664,8 +1706,6 @@ void Application::init() {
|
|||
_headMouseX = _mouseX = _glWidget->width() / 2;
|
||||
_headMouseY = _mouseY = _glWidget->height() / 2;
|
||||
|
||||
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
|
||||
|
||||
_myAvatar.init();
|
||||
_myAvatar.setPosition(START_LOCATION);
|
||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
|
@ -1682,7 +1722,7 @@ void Application::init() {
|
|||
LeapManager::initialize();
|
||||
|
||||
gettimeofday(&_timerStart, NULL);
|
||||
gettimeofday(&_lastTimeIdle, NULL);
|
||||
gettimeofday(&_lastTimeUpdated, NULL);
|
||||
|
||||
loadSettings();
|
||||
if (!shouldDynamicallySetJitterBuffer()) {
|
||||
|
@ -1691,12 +1731,35 @@ void Application::init() {
|
|||
|
||||
printLog("Loaded settings.\n");
|
||||
|
||||
|
||||
sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL());
|
||||
|
||||
_palette.init(_glWidget->width(), _glWidget->height());
|
||||
_palette.addAction(_addVoxelMode, 0, 0);
|
||||
_palette.addAction(_deleteVoxelMode, 0, 1);
|
||||
_palette.addTool(&_swatch);
|
||||
_palette.addAction(_colorVoxelMode, 0, 2);
|
||||
_palette.addAction(_eyedropperMode, 0, 3);
|
||||
_palette.addAction(_selectVoxelMode, 0, 4);
|
||||
}
|
||||
|
||||
const float MAX_AVATAR_EDIT_VELOCITY = 1.0f;
|
||||
const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
||||
const float HEAD_SPHERE_RADIUS = 0.07;
|
||||
|
||||
bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition) {
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
|
||||
Avatar* avatar = (Avatar *) node->getLinkedData();
|
||||
glm::vec3 headPosition = avatar->getHead().getPosition();
|
||||
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) {
|
||||
eyePosition = avatar->getHead().getEyeLevelPosition();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
// Use Transmitter Hand to move hand if connected, else use mouse
|
||||
|
@ -1724,8 +1787,15 @@ void Application::update(float deltaTime) {
|
|||
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||
glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
glm::vec3 eyePosition;
|
||||
if (isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition)) {
|
||||
// If the mouse is over another avatar's head...
|
||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
} else {
|
||||
glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
}
|
||||
|
||||
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
|
||||
const float VOXEL_GRAB_THRUST = 0.0f;
|
||||
|
@ -1821,20 +1891,19 @@ void Application::update(float deltaTime) {
|
|||
if (_myAvatar.getMode() == AVATAR_MODE_WALKING) {
|
||||
_handControl.stop();
|
||||
}
|
||||
|
||||
// Update from Mouse
|
||||
if (_mouseLook->isChecked()) {
|
||||
QPoint mouse = QCursor::pos();
|
||||
_myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(),
|
||||
_glWidget->mapFromGlobal(mouse).y(),
|
||||
_glWidget->width(),
|
||||
_glWidget->height());
|
||||
}
|
||||
|
||||
|
||||
// Update from Touch
|
||||
if (_isTouchPressed && _touchLook->isChecked()) {
|
||||
_myAvatar.updateFromTouch(_touchAvgX - _touchDragStartedAvgX,
|
||||
_touchAvgY - _touchDragStartedAvgY);
|
||||
if (_isTouchPressed) {
|
||||
float TOUCH_YAW_SCALE = -50.0f;
|
||||
float TOUCH_PITCH_SCALE = -50.0f;
|
||||
_myAvatar.getHead().addYaw((_touchAvgX - _lastTouchAvgX)
|
||||
* TOUCH_YAW_SCALE
|
||||
* deltaTime);
|
||||
_myAvatar.getHead().addPitch((_touchAvgY - _lastTouchAvgY)
|
||||
* TOUCH_PITCH_SCALE
|
||||
* deltaTime);
|
||||
_lastTouchAvgX = _touchAvgX;
|
||||
_lastTouchAvgY = _touchAvgY;
|
||||
}
|
||||
|
||||
// Leap finger-sensing device
|
||||
|
@ -1925,7 +1994,7 @@ void Application::update(float deltaTime) {
|
|||
if (_bandwidthDialog) {
|
||||
_bandwidthDialog->update();
|
||||
}
|
||||
|
||||
|
||||
// Update audio stats for procedural sounds
|
||||
#ifndef _WIN32
|
||||
_audio.setLastAcceleration(_myAvatar.getThrust());
|
||||
|
@ -1936,11 +2005,11 @@ void Application::update(float deltaTime) {
|
|||
|
||||
void Application::updateAvatar(float deltaTime) {
|
||||
|
||||
// Update my avatar's head position from gyros and/or webcam
|
||||
_myAvatar.updateHeadFromGyrosAndOrWebcam(_gyroLook->isChecked(),
|
||||
glm::vec3(_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale));
|
||||
// Update my avatar's state from gyros and/or webcam
|
||||
_myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(),
|
||||
glm::vec3(_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale));
|
||||
|
||||
if (_serialHeadSensor.isActive()) {
|
||||
|
||||
|
@ -1962,6 +2031,17 @@ void Application::updateAvatar(float deltaTime) {
|
|||
_headMouseY = max(_headMouseY, 0);
|
||||
_headMouseY = min(_headMouseY, _glWidget->height());
|
||||
|
||||
// Set lookAtPosition if an avatar is at the center of the screen
|
||||
|
||||
glm::vec3 screenCenterRayOrigin, screenCenterRayDirection;
|
||||
_viewFrustum.computePickRay(0.5, 0.5, screenCenterRayOrigin, screenCenterRayDirection);
|
||||
|
||||
glm::vec3 eyePosition;
|
||||
if (isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition)) {
|
||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (OculusManager::isConnected()) {
|
||||
|
@ -2215,6 +2295,15 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
void Application::displaySide(Camera& whichCamera) {
|
||||
// transform by eye offset
|
||||
|
||||
// flip x if in mirror mode (also requires reversing winding order for backface culling)
|
||||
if (_lookingInMirror->isChecked()) {
|
||||
glScalef(-1.0f, 1.0f, 1.0f);
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
} else {
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
glm::vec3 eyeOffsetPos = whichCamera.getEyeOffsetPosition();
|
||||
glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation();
|
||||
glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient);
|
||||
|
@ -2250,6 +2339,9 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
|
||||
if (_renderStarsOn->isChecked()) {
|
||||
if (!_stars.getFileLoaded()) {
|
||||
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
|
||||
}
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
// compute starfield alpha based on distance from atmosphere
|
||||
|
@ -2348,6 +2440,7 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
|
||||
// brad's frustum for debugging
|
||||
if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum);
|
||||
|
||||
}
|
||||
|
||||
void Application::displayOverlay() {
|
||||
|
@ -2396,6 +2489,9 @@ void Application::displayOverlay() {
|
|||
|
||||
if (_renderStatsOn->isChecked()) { displayStats(); }
|
||||
|
||||
// testing rendering coverage map
|
||||
if (_renderCoverageMapV2->isChecked()) { renderCoverageMapV2(); }
|
||||
if (_renderCoverageMap->isChecked()) { renderCoverageMap(); }
|
||||
if (_bandwidthDisplayOn->isChecked()) { _bandwidthMeter.render(_glWidget->width(), _glWidget->height()); }
|
||||
|
||||
if (_logOn->isChecked()) { LogDisplay::instance.render(_glWidget->width(), _glWidget->height()); }
|
||||
|
@ -2408,7 +2504,7 @@ void Application::displayOverlay() {
|
|||
// Show on-screen msec timer
|
||||
if (_renderFrameTimerOn->isChecked()) {
|
||||
char frameTimer[10];
|
||||
long long mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5);
|
||||
uint64_t mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5);
|
||||
sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000));
|
||||
drawtext(_glWidget->width() - 100, _glWidget->height() - 20, 0.30, 0, 1.0, 0, frameTimer, 0, 0, 0);
|
||||
drawtext(_glWidget->width() - 102, _glWidget->height() - 22, 0.30, 0, 1.0, 0, frameTimer, 1, 1, 1);
|
||||
|
@ -2440,7 +2536,52 @@ void Application::displayOverlay() {
|
|||
|
||||
// render the webcam input frame
|
||||
_webcam.renderPreview(_glWidget->width(), _glWidget->height());
|
||||
|
||||
|
||||
_palette.render(_glWidget->width(), _glWidget->height());
|
||||
|
||||
if (_eyedropperMode->isChecked() && _voxelPaintColor->data().value<QColor>() != _swatch.getColor()) {
|
||||
QColor color = _voxelPaintColor->data().value<QColor>();
|
||||
TextRenderer textRenderer(SANS_FONT_FAMILY, 11, 50);
|
||||
const char line1[] = "Assign this color to a swatch";
|
||||
const char line2[] = "by choosing a key from 1 to 8.";
|
||||
|
||||
int left = (_glWidget->width() - POPUP_WIDTH - 2 * POPUP_MARGIN) / 2;
|
||||
int top = _glWidget->height() / 40;
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
for (double a = M_PI; a < 1.5f * M_PI; a += POPUP_STEP) {
|
||||
glVertex2f(left + POPUP_MARGIN * cos(a) , top + POPUP_MARGIN * sin(a));
|
||||
}
|
||||
for (double a = 1.5f * M_PI; a < 2.0f * M_PI; a += POPUP_STEP) {
|
||||
glVertex2f(left + POPUP_WIDTH + POPUP_MARGIN * cos(a), top + POPUP_MARGIN * sin(a));
|
||||
}
|
||||
for (double a = 0.0f; a < 0.5f * M_PI; a += POPUP_STEP) {
|
||||
glVertex2f(left + POPUP_WIDTH + POPUP_MARGIN * cos(a), top + POPUP_HEIGHT + POPUP_MARGIN * sin(a));
|
||||
}
|
||||
for (double a = 0.5f * M_PI; a < 1.0f * M_PI; a += POPUP_STEP) {
|
||||
glVertex2f(left + POPUP_MARGIN * cos(a) , top + POPUP_HEIGHT + POPUP_MARGIN * sin(a));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(color.redF(),
|
||||
color.greenF(),
|
||||
color.blueF());
|
||||
glVertex2f(left , top);
|
||||
glVertex2f(left + SWATCH_WIDTH, top);
|
||||
glVertex2f(left + SWATCH_WIDTH, top + SWATCH_HEIGHT);
|
||||
glVertex2f(left , top + SWATCH_HEIGHT);
|
||||
glEnd();
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
textRenderer.draw(left + SWATCH_WIDTH + POPUP_MARGIN, top + FIRST_LINE_OFFSET , line1);
|
||||
textRenderer.draw(left + SWATCH_WIDTH + POPUP_MARGIN, top + SECOND_LINE_OFFSET, line2);
|
||||
}
|
||||
else {
|
||||
_swatch.checkColor();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
@ -2536,8 +2677,8 @@ void Application::renderThrustAtVoxel(const glm::vec3& thrust) {
|
|||
glVertex3f(voxelTouched.x + thrust.x, voxelTouched.y + thrust.y, voxelTouched.z + thrust.z);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::renderLineToTouchedVoxel() {
|
||||
// Draw a teal line to the voxel I am currently dragging on
|
||||
if (_mousePressed) {
|
||||
|
@ -2552,6 +2693,149 @@ void Application::renderLineToTouchedVoxel() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
||||
float horizontalScale = _glWidget->width() / 2.0f;
|
||||
float verticalScale = _glWidget->height() / 2.0f;
|
||||
|
||||
// -1,-1 is 0,windowHeight
|
||||
// 1,1 is windowWidth,0
|
||||
|
||||
// -1,1 1,1
|
||||
// +-----------------------+
|
||||
// | | |
|
||||
// | | |
|
||||
// | -1,0 | |
|
||||
// |-----------+-----------|
|
||||
// | 0,0 |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// +-----------------------+
|
||||
// -1,-1 1,-1
|
||||
|
||||
glm::vec2 screenPoint((projectedPoint.x + 1.0) * horizontalScale,
|
||||
((projectedPoint.y + 1.0) * -verticalScale) + _glWidget->height());
|
||||
|
||||
return screenPoint;
|
||||
}
|
||||
|
||||
// render the coverage map on screen
|
||||
void Application::renderCoverageMapV2() {
|
||||
|
||||
//printLog("renderCoverageMap()\n");
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(0,1,1);
|
||||
|
||||
renderCoverageMapsV2Recursively(&_voxels.myCoverageMapV2);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void Application::renderCoverageMapsV2Recursively(CoverageMapV2* map) {
|
||||
// render ourselves...
|
||||
if (map->isCovered()) {
|
||||
BoundingBox box = map->getBoundingBox();
|
||||
|
||||
glm::vec2 firstPoint = getScaledScreenPoint(box.getVertex(0));
|
||||
glm::vec2 lastPoint(firstPoint);
|
||||
|
||||
for (int i = 1; i < box.getVertexCount(); i++) {
|
||||
glm::vec2 thisPoint = getScaledScreenPoint(box.getVertex(i));
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(thisPoint.x, thisPoint.y);
|
||||
lastPoint = thisPoint;
|
||||
}
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(firstPoint.x, firstPoint.y);
|
||||
} else {
|
||||
// iterate our children and call render on them.
|
||||
for (int i = 0; i < CoverageMapV2::NUMBER_OF_CHILDREN; i++) {
|
||||
CoverageMapV2* childMap = map->getChild(i);
|
||||
if (childMap) {
|
||||
renderCoverageMapsV2Recursively(childMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render the coverage map on screen
|
||||
void Application::renderCoverageMap() {
|
||||
|
||||
//printLog("renderCoverageMap()\n");
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(0,0,1);
|
||||
|
||||
renderCoverageMapsRecursively(&_voxels.myCoverageMap);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void Application::renderCoverageMapsRecursively(CoverageMap* map) {
|
||||
for (int i = 0; i < map->getPolygonCount(); i++) {
|
||||
|
||||
VoxelProjectedPolygon* polygon = map->getPolygon(i);
|
||||
|
||||
if (polygon->getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.5,0,0); // dark red
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT)) {
|
||||
glColor3f(.5,.5,0); // dark yellow
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT)) {
|
||||
glColor3f(.5,.5,.5); // gray
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.5,0,.5); // dark magenta
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.75,0,0); // red
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP)) {
|
||||
glColor3f(1,0,1); // magenta
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_TOP)) {
|
||||
glColor3f(0,0,1); // Blue
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT | PROJECTION_TOP)) {
|
||||
glColor3f(0,1,0); // green
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR)) {
|
||||
glColor3f(1,1,0); // yellow
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_FAR | PROJECTION_RIGHT | PROJECTION_BOTTOM)) {
|
||||
glColor3f(0,.5,.5); // dark cyan
|
||||
} else {
|
||||
glColor3f(1,0,0);
|
||||
}
|
||||
|
||||
glm::vec2 firstPoint = getScaledScreenPoint(polygon->getVertex(0));
|
||||
glm::vec2 lastPoint(firstPoint);
|
||||
|
||||
for (int i = 1; i < polygon->getVertexCount(); i++) {
|
||||
glm::vec2 thisPoint = getScaledScreenPoint(polygon->getVertex(i));
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(thisPoint.x, thisPoint.y);
|
||||
lastPoint = thisPoint;
|
||||
}
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(firstPoint.x, firstPoint.y);
|
||||
}
|
||||
|
||||
// iterate our children and call render on them.
|
||||
for (int i = 0; i < CoverageMapV2::NUMBER_OF_CHILDREN; i++) {
|
||||
CoverageMap* childMap = map->getChild(i);
|
||||
if (childMap) {
|
||||
renderCoverageMapsRecursively(childMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// renderViewFrustum()
|
||||
//
|
||||
|
@ -2815,6 +3099,7 @@ void Application::eyedropperVoxelUnderCursor() {
|
|||
}
|
||||
|
||||
void Application::goHome() {
|
||||
printLog("Going Home!\n");
|
||||
_myAvatar.setPosition(START_LOCATION);
|
||||
}
|
||||
|
||||
|
@ -2992,7 +3277,8 @@ void Application::loadSettings(QSettings* settings) {
|
|||
settings->endGroup();
|
||||
|
||||
scanMenuBar(&Application::loadAction, settings);
|
||||
getAvatar()->loadData(settings);
|
||||
getAvatar()->loadData(settings);
|
||||
_swatch.loadData(settings);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3014,6 +3300,7 @@ void Application::saveSettings(QSettings* settings) {
|
|||
|
||||
scanMenuBar(&Application::saveAction, settings);
|
||||
getAvatar()->saveData(settings);
|
||||
_swatch.saveData(settings);
|
||||
}
|
||||
|
||||
void Application::importSettings() {
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "Webcam.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
#include "ToolsPalette.h"
|
||||
#include "Swatch.h"
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
|
@ -129,16 +131,17 @@ private slots:
|
|||
void doFalseRandomizeEveryOtherVoxelColors();
|
||||
void doFalseColorizeByDistance();
|
||||
void doFalseColorizeOccluded();
|
||||
void doFalseColorizeOccludedV2();
|
||||
void doFalseColorizeInView();
|
||||
void doTrueVoxelColors();
|
||||
void doTreeStats();
|
||||
void setWantsMonochrome(bool wantsMonochrome);
|
||||
void setWantsResIn(bool wantsResIn);
|
||||
void setWantsDelta(bool wantsDelta);
|
||||
void setWantsOcclusionCulling(bool wantsOcclusionCulling);
|
||||
void disableOcclusionCulling(bool disableOcclusionCulling);
|
||||
void updateVoxelModeActions();
|
||||
void decreaseVoxelSize();
|
||||
void increaseVoxelSize();
|
||||
void resetSwatchColors();
|
||||
void chooseVoxelPaintColor();
|
||||
void loadSettings(QSettings* set = NULL);
|
||||
void saveSettings(QSettings* set = NULL);
|
||||
|
@ -150,6 +153,16 @@ private slots:
|
|||
void copyVoxels();
|
||||
void pasteVoxels();
|
||||
void runTests();
|
||||
|
||||
void renderCoverageMap();
|
||||
void renderCoverageMapsRecursively(CoverageMap* map);
|
||||
|
||||
void renderCoverageMapV2();
|
||||
void renderCoverageMapsV2Recursively(CoverageMapV2* map);
|
||||
|
||||
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
||||
void goHome();
|
||||
|
||||
private:
|
||||
|
||||
static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes,
|
||||
|
@ -168,6 +181,7 @@ private:
|
|||
void init();
|
||||
|
||||
void update(float deltaTime);
|
||||
bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition);
|
||||
void updateAvatar(float deltaTime);
|
||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||
|
||||
|
@ -184,7 +198,6 @@ private:
|
|||
void maybeEditVoxelUnderCursor();
|
||||
void deleteVoxelUnderCursor();
|
||||
void eyedropperVoxelUnderCursor();
|
||||
void goHome();
|
||||
void resetSensors();
|
||||
|
||||
void setMenuShortcutsEnabled(bool enabled);
|
||||
|
@ -211,8 +224,6 @@ private:
|
|||
QAction* _shouldLowPassFilter; // Use test lowpass filter
|
||||
QAction* _gyroLook; // Whether to allow the gyro data from head to move your view
|
||||
QAction* _renderAvatarBalls; // Switch between voxels and joints/balls for avatar render
|
||||
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
|
||||
QAction* _touchLook; // Whether a 2-finger touch may be used to control look direction
|
||||
QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view
|
||||
QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar
|
||||
QAction* _gravityUse; // Whether gravity is on or not
|
||||
|
@ -244,6 +255,9 @@ private:
|
|||
QAction* _fullScreenMode; // whether we are in full screen mode
|
||||
QAction* _frustumRenderModeAction;
|
||||
QAction* _settingsAutosave; // Whether settings are saved automatically
|
||||
|
||||
QAction* _renderCoverageMapV2;
|
||||
QAction* _renderCoverageMap;
|
||||
|
||||
BandwidthMeter _bandwidthMeter;
|
||||
BandwidthDialog* _bandwidthDialog;
|
||||
|
@ -260,7 +274,7 @@ private:
|
|||
float _fps;
|
||||
timeval _applicationStartupTime;
|
||||
timeval _timerStart, _timerEnd;
|
||||
timeval _lastTimeIdle;
|
||||
timeval _lastTimeUpdated;
|
||||
bool _justStarted;
|
||||
|
||||
Stars _stars;
|
||||
|
@ -312,6 +326,8 @@ private:
|
|||
|
||||
float _touchAvgX;
|
||||
float _touchAvgY;
|
||||
float _lastTouchAvgX;
|
||||
float _lastTouchAvgY;
|
||||
float _touchDragStartedAvgX;
|
||||
float _touchDragStartedAvgY;
|
||||
bool _isTouchPressed; // true if multitouch has been pressed (clear when finished)
|
||||
|
@ -360,7 +376,12 @@ private:
|
|||
int _packetsPerSecond;
|
||||
int _bytesPerSecond;
|
||||
int _bytesCount;
|
||||
|
||||
StDev _idleLoopStdev;
|
||||
float _idleLoopMeasuredJitter;
|
||||
|
||||
ToolsPalette _palette;
|
||||
Swatch _swatch;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Application__) */
|
||||
|
|
|
@ -148,121 +148,121 @@ void Avatar::initializeBodyBalls() {
|
|||
_bodyBall[ BODY_BALL_HEAD_BASE ].radius = 0.07;
|
||||
_bodyBall[ BODY_BALL_LEFT_COLLAR ].radius = 0.04;
|
||||
_bodyBall[ BODY_BALL_LEFT_SHOULDER ].radius = 0.03;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_LEFT_FINGERTIPS ].radius = 0.01;
|
||||
_bodyBall[ BODY_BALL_RIGHT_COLLAR ].radius = 0.04;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].radius = 0.03;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].radius = 0.03;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].radius = 0.02;
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].radius = 0.01;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].radius = 0.04;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].radius = 0.04;
|
||||
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH ].radius = 0.03;
|
||||
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].radius = 0.04;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].radius = 0.04;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].radius = 0.025;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].radius = 0.025;
|
||||
|
||||
|
||||
// specify the parent joint for each ball
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentJoint = AVATAR_JOINT_PELVIS;
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentJoint = AVATAR_JOINT_PELVIS;
|
||||
_bodyBall[ BODY_BALL_TORSO ].parentJoint = AVATAR_JOINT_TORSO;
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentJoint = AVATAR_JOINT_CHEST;
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentJoint = AVATAR_JOINT_NECK_BASE;
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentJoint = AVATAR_JOINT_CHEST;
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentJoint = AVATAR_JOINT_NECK_BASE;
|
||||
_bodyBall[ BODY_BALL_HEAD_BASE ].parentJoint = AVATAR_JOINT_HEAD_BASE;
|
||||
_bodyBall[ BODY_BALL_HEAD_TOP ].parentJoint = AVATAR_JOINT_HEAD_TOP;
|
||||
_bodyBall[ BODY_BALL_LEFT_COLLAR ].parentJoint = AVATAR_JOINT_LEFT_COLLAR;
|
||||
_bodyBall[ BODY_BALL_LEFT_SHOULDER ].parentJoint = AVATAR_JOINT_LEFT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentJoint = AVATAR_JOINT_LEFT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentJoint = AVATAR_JOINT_LEFT_WRIST;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentJoint = AVATAR_JOINT_LEFT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentJoint = AVATAR_JOINT_LEFT_WRIST;
|
||||
_bodyBall[ BODY_BALL_LEFT_FINGERTIPS ].parentJoint = AVATAR_JOINT_LEFT_FINGERTIPS;
|
||||
_bodyBall[ BODY_BALL_RIGHT_COLLAR ].parentJoint = AVATAR_JOINT_RIGHT_COLLAR;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentJoint = AVATAR_JOINT_RIGHT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentJoint = AVATAR_JOINT_RIGHT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentJoint = AVATAR_JOINT_RIGHT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentJoint = AVATAR_JOINT_RIGHT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].parentJoint = AVATAR_JOINT_RIGHT_WRIST;
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].parentJoint = AVATAR_JOINT_RIGHT_FINGERTIPS;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentJoint = AVATAR_JOINT_LEFT_HIP;
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentJoint = AVATAR_JOINT_LEFT_KNEE;
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentJoint = AVATAR_JOINT_LEFT_HEEL;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentJoint = AVATAR_JOINT_LEFT_TOES;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentJoint = AVATAR_JOINT_RIGHT_HIP;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentJoint = AVATAR_JOINT_RIGHT_KNEE;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentJoint = AVATAR_JOINT_RIGHT_HEEL;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentJoint = AVATAR_JOINT_RIGHT_TOES;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentJoint = AVATAR_JOINT_LEFT_HIP;
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentJoint = AVATAR_JOINT_LEFT_KNEE;
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentJoint = AVATAR_JOINT_LEFT_HEEL;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentJoint = AVATAR_JOINT_LEFT_TOES;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentJoint = AVATAR_JOINT_RIGHT_HIP;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentJoint = AVATAR_JOINT_RIGHT_KNEE;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentJoint = AVATAR_JOINT_RIGHT_HEEL;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentJoint = AVATAR_JOINT_RIGHT_TOES;
|
||||
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH].parentJoint = AVATAR_JOINT_LEFT_HIP;
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH ].parentJoint = AVATAR_JOINT_LEFT_HIP;
|
||||
|
||||
// specify the parent offset for each ball
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_TORSO ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_HEAD_BASE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_HEAD_TOP ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_COLLAR ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_SHOULDER ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_FINGERTIPS ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_COLLAR ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentOffset = glm::vec3(0.0, 0.0, 0.0);
|
||||
|
||||
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH].parentOffset = glm::vec3(-0.1, -0.1, 0.0);
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH ].parentOffset = glm::vec3(-0.1, -0.1, 0.0);
|
||||
|
||||
|
||||
// specify the parent BALL for each ball
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentBall = BODY_BALL_NULL;
|
||||
_bodyBall[ BODY_BALL_PELVIS ].parentBall = BODY_BALL_NULL;
|
||||
_bodyBall[ BODY_BALL_TORSO ].parentBall = BODY_BALL_PELVIS;
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentBall = BODY_BALL_TORSO;
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentBall = BODY_BALL_CHEST;
|
||||
_bodyBall[ BODY_BALL_CHEST ].parentBall = BODY_BALL_TORSO;
|
||||
_bodyBall[ BODY_BALL_NECK_BASE ].parentBall = BODY_BALL_CHEST;
|
||||
_bodyBall[ BODY_BALL_HEAD_BASE ].parentBall = BODY_BALL_NECK_BASE;
|
||||
_bodyBall[ BODY_BALL_HEAD_TOP ].parentBall = BODY_BALL_HEAD_BASE;
|
||||
_bodyBall[ BODY_BALL_LEFT_COLLAR ].parentBall = BODY_BALL_CHEST;
|
||||
_bodyBall[ BODY_BALL_LEFT_SHOULDER ].parentBall = BODY_BALL_LEFT_COLLAR;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentBall = BODY_BALL_LEFT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentBall = BODY_BALL_LEFT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_LEFT_ELBOW ].parentBall = BODY_BALL_LEFT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_LEFT_WRIST ].parentBall = BODY_BALL_LEFT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_LEFT_FINGERTIPS ].parentBall = BODY_BALL_LEFT_WRIST;
|
||||
_bodyBall[ BODY_BALL_RIGHT_COLLAR ].parentBall = BODY_BALL_CHEST;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentBall = BODY_BALL_RIGHT_COLLAR;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentBall = BODY_BALL_RIGHT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_RIGHT_SHOULDER ].parentBall = BODY_BALL_RIGHT_COLLAR;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].parentBall = BODY_BALL_RIGHT_SHOULDER;
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].parentBall = BODY_BALL_RIGHT_ELBOW;
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].parentBall = BODY_BALL_RIGHT_WRIST;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentBall = BODY_BALL_PELVIS;
|
||||
_bodyBall[ BODY_BALL_LEFT_HIP ].parentBall = BODY_BALL_PELVIS;
|
||||
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH ].parentBall = BODY_BALL_LEFT_HIP;
|
||||
//_bodyBall[ BODY_BALL_LEFT_MID_THIGH ].parentBall = BODY_BALL_LEFT_HIP;
|
||||
|
||||
// _bodyBall[ BODY_BALL_LEFT_KNEE ].parentBall = BODY_BALL_LEFT_MID_THIGH;
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentBall = BODY_BALL_LEFT_HIP;
|
||||
//_bodyBall[ BODY_BALL_LEFT_KNEE ].parentBall = BODY_BALL_LEFT_MID_THIGH;
|
||||
_bodyBall[ BODY_BALL_LEFT_KNEE ].parentBall = BODY_BALL_LEFT_HIP;
|
||||
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentBall = BODY_BALL_LEFT_KNEE;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentBall = BODY_BALL_LEFT_HEEL;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentBall = BODY_BALL_PELVIS;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentBall = BODY_BALL_RIGHT_HIP;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentBall = BODY_BALL_RIGHT_KNEE;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentBall = BODY_BALL_RIGHT_HEEL;
|
||||
_bodyBall[ BODY_BALL_LEFT_HEEL ].parentBall = BODY_BALL_LEFT_KNEE;
|
||||
_bodyBall[ BODY_BALL_LEFT_TOES ].parentBall = BODY_BALL_LEFT_HEEL;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HIP ].parentBall = BODY_BALL_PELVIS;
|
||||
_bodyBall[ BODY_BALL_RIGHT_KNEE ].parentBall = BODY_BALL_RIGHT_HIP;
|
||||
_bodyBall[ BODY_BALL_RIGHT_HEEL ].parentBall = BODY_BALL_RIGHT_KNEE;
|
||||
_bodyBall[ BODY_BALL_RIGHT_TOES ].parentBall = BODY_BALL_RIGHT_HEEL;
|
||||
|
||||
/*
|
||||
// to aid in hand-shaking and hand-holding, the right hand is not collidable
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].isCollidable = false;
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].isCollidable = false;
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS].isCollidable = false;
|
||||
_bodyBall[ BODY_BALL_RIGHT_ELBOW ].isCollidable = false;
|
||||
_bodyBall[ BODY_BALL_RIGHT_WRIST ].isCollidable = false;
|
||||
_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].isCollidable = false;
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -285,24 +285,37 @@ void Avatar::reset() {
|
|||
}
|
||||
|
||||
// Update avatar head rotation with sensor data
|
||||
void Avatar::updateHeadFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle) {
|
||||
|
||||
void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle) {
|
||||
SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor();
|
||||
Webcam* webcam = Application::getInstance()->getWebcam();
|
||||
glm::vec3 estimatedPosition, estimatedRotation;
|
||||
if (gyros->isActive()) {
|
||||
if (webcam->isActive()) {
|
||||
estimatedPosition = webcam->getEstimatedPosition();
|
||||
}
|
||||
estimatedRotation = gyros->getEstimatedRotation();
|
||||
|
||||
|
||||
} else if (webcam->isActive()) {
|
||||
estimatedPosition = webcam->getEstimatedPosition();
|
||||
estimatedRotation = webcam->getEstimatedRotation();
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (webcam->isActive()) {
|
||||
estimatedPosition = webcam->getEstimatedPosition();
|
||||
|
||||
// compute and store the joint rotations
|
||||
const JointVector& joints = webcam->getEstimatedJoints();
|
||||
_joints.clear();
|
||||
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
|
||||
if (joints.size() > i && joints[i].isValid) {
|
||||
JointData data = { i, joints[i].rotation };
|
||||
_joints.push_back(data);
|
||||
|
||||
if (i == AVATAR_JOINT_CHEST) {
|
||||
// if we have a chest rotation, don't apply lean based on head
|
||||
estimatedPosition = glm::vec3();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_head.setPitch(estimatedRotation.x * amplifyAngle.x);
|
||||
_head.setYaw(estimatedRotation.y * amplifyAngle.y);
|
||||
_head.setRoll(estimatedRotation.z * amplifyAngle.z);
|
||||
|
@ -311,7 +324,7 @@ void Avatar::updateHeadFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& ampl
|
|||
// Update torso lean distance based on accelerometer data
|
||||
const float TORSO_LENGTH = 0.5f;
|
||||
const float MAX_LEAN = 45.0f;
|
||||
_head.setLeanSideways(glm::clamp(glm::degrees(atanf(-estimatedPosition.x * _leanScale / TORSO_LENGTH)),
|
||||
_head.setLeanSideways(glm::clamp(glm::degrees(atanf(estimatedPosition.x * _leanScale / TORSO_LENGTH)),
|
||||
-MAX_LEAN, MAX_LEAN));
|
||||
_head.setLeanForward(glm::clamp(glm::degrees(atanf(estimatedPosition.z * _leanScale / TORSO_LENGTH)),
|
||||
-MAX_LEAN, MAX_LEAN));
|
||||
|
@ -337,34 +350,7 @@ glm::vec3 Avatar::getUprightHeadPosition() const {
|
|||
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, _pelvisToHeadLength, 0.0f);
|
||||
}
|
||||
|
||||
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
|
||||
// Update head yaw and pitch based on mouse input
|
||||
const float MOUSE_ROTATE_SPEED = 0.01f;
|
||||
const float MOUSE_PITCH_SPEED = 0.02f;
|
||||
const int TITLE_BAR_HEIGHT = 46;
|
||||
|
||||
if ((mouseX > 1) && (mouseX < screenWidth) && (mouseY > TITLE_BAR_HEIGHT) && (mouseY < screenHeight)) {
|
||||
//
|
||||
// Mouse must be inside screen (not at edge) and not on title bar for movement to happen
|
||||
//
|
||||
|
||||
int pixelMoveThreshold = screenWidth / 6;
|
||||
glm::vec2 mouseVector(mouseX - (screenWidth / 2), mouseY - (screenHeight / 2));
|
||||
if (glm::length(mouseVector) > pixelMoveThreshold) {
|
||||
mouseVector -= glm::normalize(mouseVector) * (float) pixelMoveThreshold;
|
||||
_head.addYaw(-mouseVector.x * MOUSE_ROTATE_SPEED);
|
||||
_head.addPitch(-mouseVector.y * MOUSE_PITCH_SPEED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::updateFromTouch(float touchAvgDistX, float touchAvgDistY) {
|
||||
const float TOUCH_ROTATE_SPEED = 0.01f;
|
||||
const float TOUCH_PITCH_SPEED = 0.02f;
|
||||
|
||||
_head.addYaw(-touchAvgDistX * TOUCH_ROTATE_SPEED);
|
||||
_head.addPitch(-touchAvgDistY * TOUCH_PITCH_SPEED);
|
||||
}
|
||||
|
||||
void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) {
|
||||
//
|
||||
|
@ -485,9 +471,18 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
|||
_skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3(
|
||||
_head.getLeanForward(), 0.0f, _head.getLeanSideways())));
|
||||
|
||||
// update avatar skeleton
|
||||
_skeleton.update(deltaTime, getOrientation(), _position);
|
||||
// apply joint data (if any) to skeleton
|
||||
bool enableHandMovement = true;
|
||||
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
|
||||
_skeleton.joint[it->jointID].rotation = it->rotation;
|
||||
|
||||
// disable hand movement if we have joint info for the right wrist
|
||||
enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST);
|
||||
}
|
||||
|
||||
// update avatar skeleton
|
||||
_skeleton.update(deltaTime, getOrientation(), _position);
|
||||
|
||||
//determine the lengths of the body springs now that we have updated the skeleton at least once
|
||||
if (!_ballSpringsInitialized) {
|
||||
for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) {
|
||||
|
@ -518,7 +513,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
|||
}
|
||||
|
||||
//update the movement of the hand and process handshaking with other avatars...
|
||||
updateHandMovementAndTouching(deltaTime);
|
||||
updateHandMovementAndTouching(deltaTime, enableHandMovement);
|
||||
_avatarTouch.simulate(deltaTime);
|
||||
|
||||
// apply gravity and collision with the ground/floor
|
||||
|
@ -698,7 +693,7 @@ void Avatar::setOrientation(const glm::quat& orientation) {
|
|||
_bodyRoll = eulerAngles.z;
|
||||
}
|
||||
|
||||
void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||
void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovement) {
|
||||
|
||||
glm::quat orientation = getOrientation();
|
||||
|
||||
|
@ -707,12 +702,14 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
|
||||
glm::vec3 transformedHandMovement
|
||||
= right * _movedHandOffset.x * 2.0f
|
||||
+ up * -_movedHandOffset.y * 2.0f
|
||||
+ front * -_movedHandOffset.y * 2.0f;
|
||||
if (enableHandMovement) {
|
||||
glm::vec3 transformedHandMovement =
|
||||
right * _movedHandOffset.x * 2.0f +
|
||||
up * -_movedHandOffset.y * 2.0f +
|
||||
front * -_movedHandOffset.y * 2.0f;
|
||||
|
||||
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
|
||||
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
|
||||
}
|
||||
|
||||
if (isMyAvatar()) {
|
||||
_avatarTouch.setMyBodyPosition(_position);
|
||||
|
@ -803,7 +800,9 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
|
||||
//constrain right arm length and re-adjust elbow position as it bends
|
||||
// NOTE - the following must be called on all avatars - not just _isMine
|
||||
updateArmIKAndConstraints(deltaTime);
|
||||
if (enableHandMovement) {
|
||||
updateArmIKAndConstraints(deltaTime);
|
||||
}
|
||||
|
||||
//Set right hand position and state to be transmitted, and also tell AvatarTouch about it
|
||||
if (isMyAvatar()) {
|
||||
|
@ -1223,7 +1222,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) {
|
|||
// Always render other people, and render myself when beyond threshold distance
|
||||
if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special
|
||||
if (alpha > 0.0f) {
|
||||
_head.render(lookingInMirror, alpha);
|
||||
_head.render(alpha);
|
||||
}
|
||||
} else if (alpha > 0.0f) {
|
||||
// Render the body ball sphere
|
||||
|
|
|
@ -87,9 +87,7 @@ public:
|
|||
void reset();
|
||||
void simulate(float deltaTime, Transmitter* transmitter);
|
||||
void updateThrust(float deltaTime, Transmitter * transmitter);
|
||||
void updateHeadFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngles);
|
||||
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
|
||||
void updateFromTouch(float touchAvgDistX, float touchAvgDistY);
|
||||
void updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngles);
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
void render(bool lookingInMirror, bool renderAvatarBalls);
|
||||
|
||||
|
@ -151,10 +149,6 @@ public:
|
|||
|
||||
// Get the position/rotation of a single body ball
|
||||
void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const;
|
||||
|
||||
//read/write avatar data
|
||||
void writeAvatarDataToFile();
|
||||
void readAvatarDataFromFile();
|
||||
|
||||
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||
|
||||
|
@ -229,7 +223,7 @@ private:
|
|||
void updateBodyBalls( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void updateHandMovementAndTouching(float deltaTime);
|
||||
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
|
||||
void updateAvatarCollisions(float deltaTime);
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
|
|
|
@ -54,6 +54,7 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_rotation(0.0f, 0.0f, 0.0f),
|
||||
_leftEyePosition(0.0f, 0.0f, 0.0f),
|
||||
_rightEyePosition(0.0f, 0.0f, 0.0f),
|
||||
_eyeLevelPosition(0.0f, 0.0f, 0.0f),
|
||||
_leftEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
||||
_rightEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
||||
_leftEarPosition(0.0f, 0.0f, 0.0f),
|
||||
|
@ -67,7 +68,6 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_audioAttack(0.0f),
|
||||
_returnSpringScale(1.0f),
|
||||
_bodyRotation(0.0f, 0.0f, 0.0f),
|
||||
_lookingInMirror(false),
|
||||
_renderLookatVectors(false),
|
||||
_mohawkTriangleFan(NULL),
|
||||
_mohawkColors(NULL),
|
||||
|
@ -223,11 +223,11 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
if (isMine && _cameraFollowsHead) {
|
||||
// If we are using gyros and using gyroLook, have the camera follow head but with a null region
|
||||
// to create stable rendering view with small head movements.
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_START = 0.05f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_MAX = 0.25f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.5f;
|
||||
const float CAMERA_STOP_TOLERANCE_DEGREES = 0.25f;
|
||||
const float CAMERA_START_TOLERANCE_DEGREES = 15.0f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_START = 0.01f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_MAX = 0.5f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.05f;
|
||||
const float CAMERA_STOP_TOLERANCE_DEGREES = 0.1f;
|
||||
const float CAMERA_START_TOLERANCE_DEGREES = 2.0f;
|
||||
float cameraHeadAngleDifference = glm::length(glm::vec2(_pitch - _cameraPitch, _yaw - _cameraYaw));
|
||||
if (_isCameraMoving) {
|
||||
_cameraFollowHeadRate = glm::clamp(_cameraFollowHeadRate * CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE,
|
||||
|
@ -269,6 +269,8 @@ void Head::calculateGeometry() {
|
|||
+ up * _scale * EYE_UP_OFFSET
|
||||
+ front * _scale * EYE_FRONT_OFFSET;
|
||||
|
||||
_eyeLevelPosition = _position + up * _scale * EYE_UP_OFFSET;
|
||||
|
||||
//calculate the eyebrow positions
|
||||
_leftEyeBrowPosition = _leftEyePosition;
|
||||
_rightEyeBrowPosition = _rightEyePosition;
|
||||
|
@ -283,11 +285,10 @@ void Head::calculateGeometry() {
|
|||
}
|
||||
|
||||
|
||||
void Head::render(bool lookingInMirror, float alpha) {
|
||||
void Head::render(float alpha) {
|
||||
|
||||
_renderAlpha = alpha;
|
||||
_lookingInMirror = lookingInMirror;
|
||||
|
||||
|
||||
calculateGeometry();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -375,8 +376,8 @@ void Head::renderMohawk() {
|
|||
} else {
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glRotatef((_lookingInMirror ? (_bodyRotation.y - _yaw) : (_bodyRotation.y + _yaw)), 0, 1, 0);
|
||||
glRotatef(_lookingInMirror ? _roll: -_roll, 0, 0, 1);
|
||||
glRotatef(_bodyRotation.y + _yaw, 0, 1, 0);
|
||||
glRotatef(-_roll, 0, 0, 1);
|
||||
glRotatef(-_pitch - _bodyRotation.x, 1, 0, 0);
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
|
@ -391,8 +392,7 @@ void Head::renderMohawk() {
|
|||
}
|
||||
|
||||
glm::quat Head::getOrientation() const {
|
||||
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(_lookingInMirror ?
|
||||
glm::vec3(_pitch, -_yaw, -_roll) : glm::vec3(_pitch, _yaw, _roll)));
|
||||
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll)));
|
||||
}
|
||||
|
||||
glm::quat Head::getCameraOrientation () const {
|
||||
|
@ -627,7 +627,7 @@ void Head::renderEyeBalls() {
|
|||
glm::vec3 rotationAxis = glm::axis(orientation);
|
||||
glRotatef(glm::angle(orientation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glScalef(EYELID_RADIUS, EYELID_RADIUS, EYELID_RADIUS);
|
||||
glRotatef(-90 * _leftEyeBlink, 1, 0, 0);
|
||||
glRotatef(-40 - 50 * _leftEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
glRotatef(180 * _leftEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
|
@ -640,7 +640,7 @@ void Head::renderEyeBalls() {
|
|||
glm::vec3 rotationAxis = glm::axis(orientation);
|
||||
glRotatef(glm::angle(orientation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glScalef(EYELID_RADIUS, EYELID_RADIUS, EYELID_RADIUS);
|
||||
glRotatef(-90 * _rightEyeBlink, 1, 0, 0);
|
||||
glRotatef(-40 - 50 * _rightEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
glRotatef(180 * _rightEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine);
|
||||
void render(bool lookingInMirror, float alpha);
|
||||
void render(float alpha);
|
||||
void renderMohawk();
|
||||
|
||||
void setScale (float scale ) { _scale = scale; }
|
||||
|
@ -53,7 +53,8 @@ public:
|
|||
glm::quat getOrientation() const;
|
||||
glm::quat getCameraOrientation () const;
|
||||
|
||||
glm::vec3 getPosition() const { return _position; }
|
||||
glm::vec3 getPosition() const { return _position; }
|
||||
const glm::vec3& getEyeLevelPosition() const { return _eyeLevelPosition; }
|
||||
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; }
|
||||
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
|
@ -88,7 +89,8 @@ private:
|
|||
glm::vec3 _position;
|
||||
glm::vec3 _rotation;
|
||||
glm::vec3 _leftEyePosition;
|
||||
glm::vec3 _rightEyePosition;
|
||||
glm::vec3 _rightEyePosition;
|
||||
glm::vec3 _eyeLevelPosition;
|
||||
glm::vec3 _leftEyeBrowPosition;
|
||||
glm::vec3 _rightEyeBrowPosition;
|
||||
glm::vec3 _leftEarPosition;
|
||||
|
@ -102,7 +104,6 @@ private:
|
|||
float _audioAttack;
|
||||
float _returnSpringScale; //strength of return springs
|
||||
glm::vec3 _bodyRotation;
|
||||
bool _lookingInMirror;
|
||||
bool _renderLookatVectors;
|
||||
HairTuft _hairTuft[NUM_HAIR_TUFTS];
|
||||
glm::vec3* _mohawkTriangleFan;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Read interface data from the gyros/accelerometer Invensense board using the SerialUSB
|
||||
//
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
#include <regex.h>
|
||||
#include <sys/time.h>
|
||||
#include <string>
|
||||
|
@ -15,6 +15,11 @@
|
|||
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
|
||||
extern "C" {
|
||||
#include <inv_tty.h>
|
||||
#include <inv_mpu.h>
|
||||
}
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
@ -24,24 +29,31 @@
|
|||
|
||||
const short NO_READ_MAXIMUM_MSECS = 3000;
|
||||
const int GRAVITY_SAMPLES = 60; // Use the first few samples to baseline values
|
||||
const int SENSOR_FUSION_SAMPLES = 20;
|
||||
const int NORTH_SAMPLES = 30;
|
||||
const int ACCELERATION_SENSOR_FUSION_SAMPLES = 20;
|
||||
const int COMPASS_SENSOR_FUSION_SAMPLES = 200;
|
||||
const int LONG_TERM_RATE_SAMPLES = 1000;
|
||||
|
||||
const bool USING_INVENSENSE_MPU9150 = 1;
|
||||
|
||||
void SerialInterface::pair() {
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
// look for a matching gyro setup
|
||||
DIR *devDir;
|
||||
struct dirent *entry;
|
||||
int matchStatus;
|
||||
regex_t regex;
|
||||
|
||||
// for now this only works on OS X, where the usb serial shows up as /dev/tty.usb*
|
||||
// for now this only works on OS X, where the usb serial shows up as /dev/tty.usb*,
|
||||
// and (possibly just Ubuntu) Linux, where it shows up as /dev/ttyACM*
|
||||
if((devDir = opendir("/dev"))) {
|
||||
while((entry = readdir(devDir))) {
|
||||
#ifdef __APPLE__
|
||||
regcomp(®ex, "tty\\.usb", REG_EXTENDED|REG_NOSUB);
|
||||
#else
|
||||
regcomp(®ex, "ttyACM", REG_EXTENDED|REG_NOSUB);
|
||||
#endif
|
||||
matchStatus = regexec(®ex, entry->d_name, (size_t) 0, NULL, 0);
|
||||
if (matchStatus == 0) {
|
||||
char *serialPortname = new char[100];
|
||||
|
@ -60,7 +72,7 @@ void SerialInterface::pair() {
|
|||
|
||||
// connect to the serial port
|
||||
void SerialInterface::initializePort(char* portname) {
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
_serialDescriptor = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
printLog("Opening SerialUSB %s: ", portname);
|
||||
|
@ -87,22 +99,17 @@ void SerialInterface::initializePort(char* portname) {
|
|||
int currentFlags = fcntl(_serialDescriptor, F_GETFL);
|
||||
fcntl(_serialDescriptor, F_SETFL, currentFlags & ~O_NONBLOCK);
|
||||
|
||||
// there are extra commands to send to the invensense when it fires up
|
||||
|
||||
// this takes it out of SLEEP
|
||||
write(_serialDescriptor, "WR686B01\n", 9);
|
||||
|
||||
// delay after the wakeup
|
||||
usleep(10000);
|
||||
// make sure there's nothing queued up to be read
|
||||
tcflush(_serialDescriptor, TCIOFLUSH);
|
||||
|
||||
// this disables streaming so there's no garbage data on reads
|
||||
write(_serialDescriptor, "SD\n", 3);
|
||||
char result[4];
|
||||
read(_serialDescriptor, result, 4);
|
||||
|
||||
// delay after disabling streaming
|
||||
usleep(10000);
|
||||
|
||||
// flush whatever was produced by the last two commands
|
||||
tcflush(_serialDescriptor, TCIOFLUSH);
|
||||
tty_set_file_descriptor(_serialDescriptor);
|
||||
mpu_init(0);
|
||||
mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);
|
||||
}
|
||||
|
||||
printLog("Connected.\n");
|
||||
|
@ -187,56 +194,39 @@ void SerialInterface::renderLevels(int width, int height) {
|
|||
}
|
||||
}
|
||||
|
||||
void convertHexToInt(unsigned char* sourceBuffer, int& destinationInt) {
|
||||
unsigned int byte[2];
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
sscanf((char*) sourceBuffer + 2 * i, "%2x", &byte[i]);
|
||||
}
|
||||
|
||||
int16_t result = (byte[0] << 8);
|
||||
result += byte[1];
|
||||
|
||||
destinationInt = result;
|
||||
}
|
||||
void SerialInterface::readData(float deltaTime) {
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
|
||||
int initialSamples = totalSamples;
|
||||
|
||||
if (USING_INVENSENSE_MPU9150) {
|
||||
unsigned char sensorBuffer[36];
|
||||
|
||||
|
||||
// ask the invensense for raw gyro data
|
||||
write(_serialDescriptor, "RD683B0E\n", 9);
|
||||
read(_serialDescriptor, sensorBuffer, 36);
|
||||
|
||||
int accelXRate, accelYRate, accelZRate;
|
||||
|
||||
convertHexToInt(sensorBuffer + 6, accelZRate);
|
||||
convertHexToInt(sensorBuffer + 10, accelYRate);
|
||||
convertHexToInt(sensorBuffer + 14, accelXRate);
|
||||
short accelData[3];
|
||||
mpu_get_accel_reg(accelData, 0);
|
||||
|
||||
const float LSB_TO_METERS_PER_SECOND2 = 1.f / 16384.f * GRAVITY_EARTH;
|
||||
// From MPU-9150 register map, with setting on
|
||||
// highest resolution = +/- 2G
|
||||
|
||||
_lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2;
|
||||
|
||||
|
||||
int rollRate, yawRate, pitchRate;
|
||||
|
||||
convertHexToInt(sensorBuffer + 22, rollRate);
|
||||
convertHexToInt(sensorBuffer + 26, yawRate);
|
||||
convertHexToInt(sensorBuffer + 30, pitchRate);
|
||||
_lastAcceleration = glm::vec3(-accelData[2], -accelData[1], -accelData[0]) * LSB_TO_METERS_PER_SECOND2;
|
||||
|
||||
short gyroData[3];
|
||||
mpu_get_gyro_reg(gyroData, 0);
|
||||
|
||||
// Convert the integer rates to floats
|
||||
const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec.
|
||||
glm::vec3 rotationRates;
|
||||
rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND;
|
||||
rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND;
|
||||
rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND;
|
||||
|
||||
rotationRates[0] = ((float) -gyroData[2]) * LSB_TO_DEGREES_PER_SECOND;
|
||||
rotationRates[1] = ((float) -gyroData[1]) * LSB_TO_DEGREES_PER_SECOND;
|
||||
rotationRates[2] = ((float) -gyroData[0]) * LSB_TO_DEGREES_PER_SECOND;
|
||||
|
||||
short compassData[3];
|
||||
mpu_get_compass_reg(compassData, 0);
|
||||
|
||||
// Convert integer values to floats, update extents
|
||||
_lastCompass = glm::vec3(compassData[2], -compassData[0], -compassData[1]);
|
||||
|
||||
// update and subtract the long term average
|
||||
_averageRotationRates = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageRotationRates +
|
||||
1.f/(float)LONG_TERM_RATE_SAMPLES * rotationRates;
|
||||
|
@ -323,19 +313,31 @@ void SerialInterface::readData(float deltaTime) {
|
|||
}
|
||||
else {
|
||||
if (totalSamples < GRAVITY_SAMPLES) {
|
||||
_gravity = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _gravity +
|
||||
1.f/(float)GRAVITY_SAMPLES * _lastAcceleration;
|
||||
_gravity = glm::mix(_gravity, _lastAcceleration, 1.0f / GRAVITY_SAMPLES);
|
||||
|
||||
// North samples start later, because the initial compass readings are screwy
|
||||
int northSample = totalSamples - (GRAVITY_SAMPLES - NORTH_SAMPLES);
|
||||
if (northSample == 0) {
|
||||
_north = _lastCompass;
|
||||
|
||||
} else if (northSample > 0) {
|
||||
_north = glm::mix(_north, _lastCompass, 1.0f / NORTH_SAMPLES);
|
||||
}
|
||||
} else {
|
||||
// Use gravity reading to do sensor fusion on the pitch and roll estimation
|
||||
estimatedRotation = safeMix(estimatedRotation,
|
||||
rotationBetween(estimatedRotation * _lastAcceleration, _gravity) * estimatedRotation,
|
||||
1.0f / SENSOR_FUSION_SAMPLES);
|
||||
1.0f / ACCELERATION_SENSOR_FUSION_SAMPLES);
|
||||
|
||||
// Without a compass heading, always decay estimated Yaw slightly
|
||||
const float YAW_DECAY = 0.999f;
|
||||
glm::vec3 forward = estimatedRotation * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
estimatedRotation = safeMix(glm::angleAxis(glm::degrees(atan2f(forward.x, -forward.z)),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f)) * estimatedRotation, estimatedRotation, YAW_DECAY);
|
||||
// Update the compass extents
|
||||
_compassMinima = glm::min(_compassMinima, _lastCompass);
|
||||
_compassMaxima = glm::max(_compassMaxima, _lastCompass);
|
||||
|
||||
// Same deal with the compass heading
|
||||
estimatedRotation = safeMix(estimatedRotation,
|
||||
rotationBetween(estimatedRotation * recenterCompass(_lastCompass),
|
||||
recenterCompass(_north)) * estimatedRotation,
|
||||
1.0f / COMPASS_SENSOR_FUSION_SAMPLES);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,13 +373,17 @@ void SerialInterface::resetAverages() {
|
|||
}
|
||||
|
||||
void SerialInterface::resetSerial() {
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
resetAverages();
|
||||
_active = false;
|
||||
gettimeofday(&lastGoodRead, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 SerialInterface::recenterCompass(const glm::vec3& compass) {
|
||||
// compensate for "hard iron" distortion by subtracting the midpoint on each axis; see
|
||||
// http://www.sensorsmag.com/sensors/motion-velocity-displacement/compensating-tilt-hard-iron-and-soft-iron-effects-6475
|
||||
return compass - (_compassMinima + _compassMaxima) * 0.5f;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "Log.h"
|
||||
|
||||
// These includes are for serial port reading/writing
|
||||
#ifdef __APPLE__
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
@ -33,11 +33,13 @@ public:
|
|||
_estimatedVelocity(0, 0, 0),
|
||||
_lastAcceleration(0, 0, 0),
|
||||
_lastRotationRates(0, 0, 0),
|
||||
_angularVelocityToLinearAccel( // experimentally derived initial values
|
||||
_compassMinima(-235, -132, -184), // experimentally derived initial values follow
|
||||
_compassMaxima(83, 155, 120),
|
||||
_angularVelocityToLinearAccel(
|
||||
0.003f, -0.001f, -0.006f,
|
||||
-0.005f, -0.001f, -0.006f,
|
||||
0.010f, 0.004f, 0.007f),
|
||||
_angularAccelToLinearAccel( // experimentally derived initial values
|
||||
_angularAccelToLinearAccel(
|
||||
0.0f, 0.0f, 0.002f,
|
||||
0.0f, 0.0f, 0.001f,
|
||||
-0.002f, -0.002f, 0.0f)
|
||||
|
@ -64,11 +66,14 @@ private:
|
|||
void initializePort(char* portname);
|
||||
void resetSerial();
|
||||
|
||||
glm::vec3 recenterCompass(const glm::vec3& compass);
|
||||
|
||||
bool _active;
|
||||
int _serialDescriptor;
|
||||
int totalSamples;
|
||||
timeval lastGoodRead;
|
||||
glm::vec3 _gravity;
|
||||
glm::vec3 _north;
|
||||
glm::vec3 _averageRotationRates;
|
||||
glm::vec3 _averageAcceleration;
|
||||
glm::vec3 _estimatedRotation;
|
||||
|
@ -77,6 +82,9 @@ private:
|
|||
glm::vec3 _estimatedAcceleration;
|
||||
glm::vec3 _lastAcceleration;
|
||||
glm::vec3 _lastRotationRates;
|
||||
glm::vec3 _lastCompass;
|
||||
glm::vec3 _compassMinima;
|
||||
glm::vec3 _compassMaxima;
|
||||
|
||||
glm::mat3 _angularVelocityToLinearAccel;
|
||||
glm::mat3 _angularAccelToLinearAccel;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "Skeleton.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f;
|
||||
const float FLOATING_HEIGHT = 0.13f;
|
||||
|
@ -18,12 +19,21 @@ void Skeleton::initialize() {
|
|||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||
joint[b].parent = AVATAR_JOINT_NULL;
|
||||
joint[b].position = glm::vec3(0.0, 0.0, 0.0);
|
||||
joint[b].defaultPosePosition = glm::vec3(0.0, 0.0, 0.0);
|
||||
joint[b].rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
joint[b].length = 0.0;
|
||||
joint[b].bindRadius = 1.0f / 8;
|
||||
}
|
||||
|
||||
// put the arms at the side
|
||||
joint[AVATAR_JOINT_LEFT_ELBOW].rotation = glm::quat(glm::vec3(0.0f, 0.0f, PIf * 0.5f));
|
||||
joint[AVATAR_JOINT_RIGHT_ELBOW].rotation = glm::quat(glm::vec3(0.0f, 0.0f, -PIf * 0.5f));
|
||||
|
||||
// bend the knees
|
||||
joint[AVATAR_JOINT_LEFT_KNEE].rotation = joint[AVATAR_JOINT_RIGHT_KNEE].rotation =
|
||||
glm::quat(glm::vec3(PIf / 8.0f, 0.0f, 0.0f));
|
||||
joint[AVATAR_JOINT_LEFT_HEEL].rotation = joint[AVATAR_JOINT_RIGHT_HEEL].rotation =
|
||||
glm::quat(glm::vec3(-PIf / 4.0f, 0.0f, 0.0f));
|
||||
|
||||
// specify the parental hierarchy
|
||||
joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
|
||||
joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
|
||||
|
@ -80,39 +90,9 @@ void Skeleton::initialize() {
|
|||
joint[ AVATAR_JOINT_RIGHT_HEEL ].bindPosePosition = glm::vec3( 0.00, -0.23, 0.00 );
|
||||
joint[ AVATAR_JOINT_RIGHT_TOES ].bindPosePosition = glm::vec3( 0.00, 0.00, -0.06 );
|
||||
|
||||
// specify the default pose position
|
||||
joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
|
||||
joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
|
||||
joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.14, 0.01 );
|
||||
joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
|
||||
joint[ AVATAR_JOINT_HEAD_TOP ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
|
||||
|
||||
joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, 0.01 );
|
||||
joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.01 );
|
||||
joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
||||
joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
||||
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
||||
|
||||
joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, 0.01 );
|
||||
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.01 );
|
||||
joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
||||
joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
||||
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
||||
|
||||
joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.02 );
|
||||
joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.01, -0.25, -0.03 );
|
||||
joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.01, -0.22, 0.08 );
|
||||
joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
|
||||
|
||||
joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.02 );
|
||||
joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( -0.01, -0.25, -0.03 );
|
||||
joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( -0.01, -0.22, 0.08 );
|
||||
joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
|
||||
|
||||
// calculate bone length, absolute bind positions/rotations
|
||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||
joint[b].length = glm::length(joint[b].defaultPosePosition);
|
||||
joint[b].length = glm::length(joint[b].bindPosePosition);
|
||||
|
||||
if (joint[b].parent == AVATAR_JOINT_NULL) {
|
||||
joint[b].absoluteBindPosePosition = joint[b].bindPosePosition;
|
||||
|
@ -122,7 +102,7 @@ void Skeleton::initialize() {
|
|||
joint[b].bindPosePosition;
|
||||
glm::vec3 parentDirection = joint[ joint[b].parent ].absoluteBindPoseRotation * JOINT_DIRECTION;
|
||||
joint[b].absoluteBindPoseRotation = rotationBetween(parentDirection, joint[b].bindPosePosition) *
|
||||
joint[ joint[b].parent ].absoluteBindPoseRotation;
|
||||
joint[ joint[b].parent ].absoluteBindPoseRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +120,7 @@ void Skeleton::update(float deltaTime, const glm::quat& orientation, glm::vec3 p
|
|||
joint[b].position = joint[ joint[b].parent ].position;
|
||||
}
|
||||
|
||||
glm::vec3 rotatedJointVector = joint[b].absoluteRotation * joint[b].defaultPosePosition;
|
||||
glm::vec3 rotatedJointVector = joint[b].absoluteRotation * joint[b].bindPosePosition;
|
||||
joint[b].position += rotatedJointVector;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ public:
|
|||
{
|
||||
AvatarJointID parent; // which joint is this joint connected to?
|
||||
glm::vec3 position; // the position at the "end" of the joint - in global space
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the default pose
|
||||
glm::vec3 bindPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::vec3 absoluteBindPosePosition; // the absolute position when the avatar is in the "T-pose"
|
||||
glm::quat absoluteBindPoseRotation; // the absolute rotation when the avatar is in the "T-pose"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#undef __interface__Starfield_impl__
|
||||
|
||||
Stars::Stars() :
|
||||
_controller(0l) {
|
||||
_controller(0l), _fileLoaded(false) {
|
||||
_controller = new starfield::Controller;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@ Stars::~Stars() {
|
|||
}
|
||||
|
||||
bool Stars::readInput(const char* url, const char* cacheFile, unsigned limit) {
|
||||
return _controller->readInput(url, cacheFile, limit);
|
||||
_fileLoaded = _controller->readInput(url, cacheFile, limit);
|
||||
return _fileLoaded;
|
||||
}
|
||||
|
||||
bool Stars::setResolution(unsigned k) {
|
||||
|
|
|
@ -65,6 +65,7 @@ class Stars {
|
|||
float changeLOD(float factor,
|
||||
float overalloc = 0.25, float realloc = 0.15);
|
||||
|
||||
bool getFileLoaded() const { return _fileLoaded; };
|
||||
private:
|
||||
// don't copy/assign
|
||||
Stars(Stars const&); // = delete;
|
||||
|
@ -73,6 +74,8 @@ class Stars {
|
|||
// variables
|
||||
|
||||
starfield::Controller* _controller;
|
||||
|
||||
bool _fileLoaded;
|
||||
};
|
||||
|
||||
|
||||
|
|
169
interface/src/Swatch.cpp
Normal file
169
interface/src/Swatch.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
#include "Swatch.h"
|
||||
#include <iostream>
|
||||
|
||||
Swatch::Swatch(QAction* action) :
|
||||
Tool(action, 0, -1, -1),
|
||||
_textRenderer(MONO_FONT_FAMILY, 10, 100),
|
||||
_selected(1) {
|
||||
}
|
||||
|
||||
void Swatch::reset() {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_colors[i].setRgb(colorBase[i][0],
|
||||
colorBase[i][1],
|
||||
colorBase[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
QColor Swatch::getColor() {
|
||||
return _colors[_selected - 1];
|
||||
}
|
||||
|
||||
void Swatch::checkColor() {
|
||||
if (_action->data().value<QColor>() == _colors[_selected - 1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPixmap map(16, 16);
|
||||
map.fill(_colors[_selected - 1]);
|
||||
_action->setData(_colors[_selected - 1]) ;
|
||||
_action->setIcon(map);
|
||||
}
|
||||
|
||||
void Swatch::saveData(QSettings* settings) {
|
||||
settings->beginGroup("Swatch");
|
||||
|
||||
for (int i(0); i < SWATCH_SIZE; ++i) {
|
||||
QString rx("R1"), gx("G1"), bx("B1");
|
||||
rx[1] = '1' + i;
|
||||
gx[1] = rx[1];
|
||||
bx[1] = rx[1];
|
||||
settings->setValue(rx, _colors[i].red());
|
||||
settings->setValue(gx, _colors[i].green());
|
||||
settings->setValue(bx, _colors[i].blue());
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void Swatch::loadData(QSettings* settings) {
|
||||
settings->beginGroup("Swatch");
|
||||
|
||||
for (int i = 0; i < SWATCH_SIZE; ++i) {
|
||||
QString rx("R1"), gx("G1"), bx("B1");
|
||||
rx[1] = '1' + i;
|
||||
gx[1] = rx[1];
|
||||
bx[1] = rx[1];
|
||||
_colors[i].setRgb(settings->value(rx, colorBase[i][0]).toInt(),
|
||||
settings->value(gx, colorBase[i][1]).toInt(),
|
||||
settings->value(bx, colorBase[i][2]).toInt());
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
|
||||
checkColor();
|
||||
}
|
||||
|
||||
void Swatch::handleEvent(int key, bool getColor) {
|
||||
int next(0);
|
||||
|
||||
switch (key) {
|
||||
case Qt::Key_1:
|
||||
next = 1;
|
||||
break;
|
||||
case Qt::Key_2:
|
||||
next = 2;
|
||||
break;
|
||||
case Qt::Key_3:
|
||||
next = 3;
|
||||
break;
|
||||
case Qt::Key_4:
|
||||
next = 4;
|
||||
break;
|
||||
case Qt::Key_5:
|
||||
next = 5;
|
||||
break;
|
||||
case Qt::Key_6:
|
||||
next = 6;
|
||||
break;
|
||||
case Qt::Key_7:
|
||||
next = 7;
|
||||
break;
|
||||
case Qt::Key_8:
|
||||
next = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (getColor) {
|
||||
if (_action->data().value<QColor>() != _colors[_selected - 1]) {
|
||||
_selected = next;
|
||||
_colors[_selected - 1] = _action->data().value<QColor>();
|
||||
}
|
||||
} else {
|
||||
_selected = next;
|
||||
QPixmap map(16, 16);
|
||||
map.fill(_colors[_selected - 1]);
|
||||
_action->setData(_colors[_selected - 1]) ;
|
||||
_action->setIcon(map);
|
||||
}
|
||||
}
|
||||
|
||||
void Swatch::render(int width, int height) {
|
||||
char str[2];
|
||||
int margin = 0.10f * height;
|
||||
height = 0.75f * height;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glVertex2f(0, 8 * (height - margin) + margin);
|
||||
glVertex2f(width, 8 * (height - margin) + margin);
|
||||
glVertex2f(width, 0);
|
||||
glVertex2f(0, 0);
|
||||
glEnd();
|
||||
|
||||
for (unsigned int i = 0; i < SWATCH_SIZE; ++i) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(_colors[i].redF(),
|
||||
_colors[i].greenF(),
|
||||
_colors[i].blueF());
|
||||
glVertex2f(margin , (i + 1) * (height - margin));
|
||||
glVertex2f(width - margin, (i + 1) * (height - margin));
|
||||
glVertex2f(width - margin, i * (height - margin) + margin);
|
||||
glVertex2f(margin , i * (height - margin) + margin);
|
||||
glEnd();
|
||||
|
||||
if (_colors[i].lightness() < 50) {
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glVertex2f(margin , (i + 1) * (height - margin));
|
||||
glVertex2f(width - margin, (i + 1) * (height - margin));
|
||||
|
||||
glVertex2f(width - margin, (i + 1) * (height - margin));
|
||||
glVertex2f(width - margin, i * (height - margin) + margin);
|
||||
|
||||
glVertex2f(width - margin, i * (height - margin) + margin);
|
||||
glVertex2f(margin , i * (height - margin) + margin);
|
||||
|
||||
glVertex2f(margin , i * (height - margin) + margin);
|
||||
glVertex2f(margin , (i + 1) * (height - margin));
|
||||
glEnd();
|
||||
} else {
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (_selected == i + 1) {
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex2f(margin , (i + 1) * (height - margin) - margin);
|
||||
glVertex2f(width/4 - margin, i * (height - margin) + height / 2.0f);
|
||||
glVertex2f(margin , i * (height - margin) + margin + margin);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
sprintf(str, "%d", i + 1);
|
||||
_textRenderer.draw(3 * width/4, (i + 1) * (height - margin) - 0.2f * height, str);
|
||||
}
|
||||
|
||||
glTranslated(0, 8 * (height - margin) + margin + 0.075f * height, 0);
|
||||
}
|
43
interface/src/Swatch.h
Normal file
43
interface/src/Swatch.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Swatch.h
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Swatch__
|
||||
#define __interface__Swatch__
|
||||
|
||||
#include "Tool.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
|
||||
static const int SWATCH_SIZE = 8;
|
||||
static const int colorBase[8][3] = {{237, 175, 0},
|
||||
{61, 211, 72},
|
||||
{51, 204, 204},
|
||||
{63, 169, 245},
|
||||
{193, 99, 122},
|
||||
{255, 54, 69},
|
||||
{124, 36, 36},
|
||||
{63, 35, 19}};
|
||||
|
||||
class Swatch : public Tool {
|
||||
public:
|
||||
Swatch(QAction* action);
|
||||
|
||||
QColor getColor();
|
||||
void checkColor();
|
||||
void saveData(QSettings* settings);
|
||||
void loadData(QSettings* settings);
|
||||
void reset();
|
||||
|
||||
void render(int width, int height);
|
||||
void handleEvent(int key, bool getColor);
|
||||
|
||||
private:
|
||||
TextRenderer _textRenderer;
|
||||
QColor _colors[SWATCH_SIZE];
|
||||
int _selected;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Swatch__) */
|
51
interface/src/Tool.cpp
Normal file
51
interface/src/Tool.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "Tool.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QGLWidget>
|
||||
|
||||
Tool::Tool(QAction *action, GLuint texture, int x, int y) :
|
||||
_action(action),
|
||||
_texture(texture),
|
||||
_x(x),
|
||||
_y(y) {
|
||||
}
|
||||
|
||||
void Tool::setAction(QAction* action) {
|
||||
_action = action;
|
||||
}
|
||||
|
||||
bool Tool::isActive() {
|
||||
return _action->isChecked();
|
||||
}
|
||||
|
||||
void Tool::render(int width, int height) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _texture);
|
||||
|
||||
|
||||
if (_action == 0 || _action->isChecked()) {
|
||||
glColor3f(1.0f, 1.0f, 1.0f); // reset gl color
|
||||
} else {
|
||||
glColor3f(0.3f, 0.3f, 0.3f);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f( _x / NUM_TOOLS_COLS, 1.0f - (_y + 1) / NUM_TOOLS_ROWS);
|
||||
glVertex2f(0 , height);
|
||||
|
||||
glTexCoord2f((_x + 1) / NUM_TOOLS_COLS, 1.0f - (_y + 1) / NUM_TOOLS_ROWS);
|
||||
glVertex2f(width, height);
|
||||
|
||||
glTexCoord2f((_x + 1) / NUM_TOOLS_COLS, 1.0f - _y / NUM_TOOLS_ROWS);
|
||||
glVertex2f(width, 0);
|
||||
|
||||
glTexCoord2f( _x / NUM_TOOLS_COLS, 1.0f - _y / NUM_TOOLS_ROWS);
|
||||
glVertex2f(0 , 0);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glTranslated(0, 1.10f * height, 0);
|
||||
}
|
55
interface/src/Tool.h
Normal file
55
interface/src/Tool.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Tool.h
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Tool__
|
||||
#define __interface__Tool__
|
||||
|
||||
#include <QAction>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Util.h"
|
||||
|
||||
class QAction;
|
||||
|
||||
|
||||
// Number of rows and columns in the SVG file for the tool palette
|
||||
static const int NUM_TOOLS_ROWS = 10;
|
||||
static const int NUM_TOOLS_COLS = 2;
|
||||
static const int SWATCHS_TOOLS_COUNT = 13; // 8 swatch + 5 tools
|
||||
|
||||
static const int WIDTH_MIN = 47; // Minimal tools width
|
||||
static const float TOOLS_RATIO = 40.0f / 60.0f; // ratio height/width of tools icons
|
||||
static const float PAL_SCREEN_RATIO = 3.0f / 100.0f; // Percentage of the screeen width the palette is going to occupy
|
||||
|
||||
// Swatch popup consts
|
||||
static const float POPUP_STEP = 0.05f;
|
||||
static const float POPUP_MARGIN = 10.0f;
|
||||
static const int POPUP_WIDTH = 280;
|
||||
static const int POPUP_HEIGHT = 30;
|
||||
static const int SWATCH_WIDTH = 64;
|
||||
static const int SWATCH_HEIGHT = 30;
|
||||
static const int FIRST_LINE_OFFSET = 12;
|
||||
static const int SECOND_LINE_OFFSET = 28;
|
||||
|
||||
class Tool {
|
||||
public:
|
||||
Tool(QAction* action, GLuint texture, int x, int y);
|
||||
|
||||
void setAction(QAction* action);
|
||||
bool isActive();
|
||||
virtual void render(int width, int height);
|
||||
|
||||
protected:
|
||||
QAction* _action;
|
||||
GLuint _texture;
|
||||
|
||||
// position in the SVG grid
|
||||
double _x;
|
||||
double _y;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Tool__) */
|
79
interface/src/ToolsPalette.cpp
Normal file
79
interface/src/ToolsPalette.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "ToolsPalette.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QGLWidget>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
void ToolsPalette::init(int screenWidth, int screenHeight) {
|
||||
_width = (PAL_SCREEN_RATIO * screenWidth < WIDTH_MIN) ? WIDTH_MIN : PAL_SCREEN_RATIO * screenWidth;
|
||||
_height = TOOLS_RATIO * _width;
|
||||
|
||||
_left = screenWidth / 150;
|
||||
_top = (screenHeight - SWATCHS_TOOLS_COUNT * _height) / 2;
|
||||
|
||||
// Load SVG
|
||||
switchToResourcesParentIfRequired();
|
||||
QSvgRenderer renderer(QString("./resources/images/hifi-interface-tools.svg"));
|
||||
|
||||
// Prepare a QImage with desired characteritisc
|
||||
QImage image(NUM_TOOLS_COLS * _width, NUM_TOOLS_ROWS * _height, QImage::Format_ARGB32);
|
||||
|
||||
// Get QPainter that paints to the image
|
||||
QPainter painter(&image);
|
||||
renderer.render(&painter);
|
||||
|
||||
//get the OpenGL-friendly image
|
||||
_textureImage = QGLWidget::convertToGLFormat(image);
|
||||
|
||||
glGenTextures(1, &_textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _textureID);
|
||||
|
||||
//generate the texture
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
_textureImage.width(),
|
||||
_textureImage.height(),
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
_textureImage.bits());
|
||||
|
||||
//texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
|
||||
void ToolsPalette::addAction(QAction* action, int x, int y) {
|
||||
Tool* tmp = new Tool(action, _textureID, x, y);
|
||||
_tools.push_back(tmp);
|
||||
}
|
||||
|
||||
void ToolsPalette::addTool(Tool* tool) {
|
||||
_tools.push_back(tool);
|
||||
}
|
||||
|
||||
void ToolsPalette::render(int screenWidth, int screenHeight) {
|
||||
_width = (PAL_SCREEN_RATIO * screenWidth < WIDTH_MIN) ? WIDTH_MIN : PAL_SCREEN_RATIO * screenWidth;
|
||||
_height = TOOLS_RATIO * _width;
|
||||
|
||||
_left = screenWidth / 150;
|
||||
_top = (screenHeight - SWATCHS_TOOLS_COUNT * _height) / 2;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslated(_left, _top, 0);
|
||||
|
||||
bool show = false;
|
||||
for (unsigned int i = 0; i < _tools.size(); ++i) {
|
||||
if (_tools[i]->isActive()) {
|
||||
show = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (show) {
|
||||
for (unsigned int i = 0; i < _tools.size(); ++i) {
|
||||
_tools[i]->render(_width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
35
interface/src/ToolsPalette.h
Normal file
35
interface/src/ToolsPalette.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ToolsPalette.h
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__ToolsPalette__
|
||||
#define __interface__ToolsPalette__
|
||||
|
||||
#include "Tool.h"
|
||||
#include "Swatch.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ToolsPalette {
|
||||
public:
|
||||
void init(int screenWidth, int screenHeight);
|
||||
void addAction(QAction* action, int x, int y);
|
||||
void addTool(Tool* tool);
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
||||
private:
|
||||
QImage _textureImage;
|
||||
GLuint _textureID;
|
||||
std::vector<Tool*> _tools;
|
||||
|
||||
int _top;
|
||||
int _left;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__ToolsPalette__) */
|
|
@ -499,6 +499,34 @@ void runTimingTests() {
|
|||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("powf(f, 0.5) usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
// Vector Math
|
||||
float distance;
|
||||
glm::vec3 pointA(randVector()), pointB(randVector());
|
||||
gettimeofday(&startTime, NULL);
|
||||
for (int i = 1; i < numTests; i++) {
|
||||
//glm::vec3 temp = pointA - pointB;
|
||||
//float distanceSquared = glm::dot(temp, temp);
|
||||
distance = glm::distance(pointA, pointB);
|
||||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("vector math usecs: %f [%f msecs total for %d tests]\n",
|
||||
1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests);
|
||||
|
||||
// Vec3 test
|
||||
glm::vec3 vecA(randVector()), vecB(randVector());
|
||||
float result;
|
||||
|
||||
gettimeofday(&startTime, NULL);
|
||||
for (int i = 1; i < numTests; i++) {
|
||||
glm::vec3 temp = vecA-vecB;
|
||||
result = glm::dot(temp,temp);
|
||||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("vec3 assign and dot() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -509,3 +537,13 @@ float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius) {
|
||||
glm::vec3 vecFromRayToSphereCenter = sphereCenter - rayStarting;
|
||||
double projection = glm::dot(vecFromRayToSphereCenter, rayNormalizedDirection);
|
||||
double shortestDistance = sqrt(glm::dot(vecFromRayToSphereCenter, vecFromRayToSphereCenter) - projection * projection);
|
||||
if (shortestDistance <= sphereRadius) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
// the standard mono font family
|
||||
#define MONO_FONT_FAMILY "Courier"
|
||||
|
||||
|
||||
void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * fwd, glm::vec3 * left, glm::vec3 * up);
|
||||
|
||||
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos);
|
||||
|
@ -72,4 +71,6 @@ void runTimingTests();
|
|||
|
||||
float loadSetting(QSettings* settings, const char* name, float defaultValue);
|
||||
|
||||
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Log.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "CoverageMap.h"
|
||||
#include "CoverageMapV2.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
|
@ -167,17 +168,17 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
|
||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||
PerformanceWarning warn(_renderWarningsOn, "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated
|
||||
long long start = usecTimestampNow();
|
||||
long long sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
|
||||
uint64_t start = usecTimestampNow();
|
||||
uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
|
||||
|
||||
bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
|
||||
if (!iAmDebugging && sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
|
||||
if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
|
||||
return; // bail early, it hasn't been long enough since the last time we ran
|
||||
}
|
||||
|
||||
long long sinceLastViewCulling = (start - _lastViewCulling) / 1000;
|
||||
uint64_t sinceLastViewCulling = (start - _lastViewCulling) / 1000;
|
||||
// If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view
|
||||
if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS))
|
||||
if ((sinceLastViewCulling >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS))
|
||||
&& !isViewChanging() && hasViewChanged()) {
|
||||
_lastViewCulling = start;
|
||||
|
||||
|
@ -191,7 +192,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
|||
// VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary.
|
||||
cleanupRemovedVoxels();
|
||||
|
||||
long long endViewCulling = usecTimestampNow();
|
||||
uint64_t endViewCulling = usecTimestampNow();
|
||||
_lastViewCullingElapsed = (endViewCulling - start) / 1000;
|
||||
}
|
||||
|
||||
|
@ -228,8 +229,8 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
|||
|
||||
pthread_mutex_unlock(&_bufferWriteLock);
|
||||
|
||||
long long end = usecTimestampNow();
|
||||
long long elapsedmsec = (end - start) / 1000;
|
||||
uint64_t end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start) / 1000;
|
||||
_setupNewVoxelsForDrawingLastFinished = end;
|
||||
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||
}
|
||||
|
@ -1088,13 +1089,13 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
|||
args.expectedMax = _voxelsInWriteArrays;
|
||||
_tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
|
||||
|
||||
printLog("_voxelsDirty=%s _voxelsInWriteArrays=%ld minDirty=%ld maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
|
||||
_voxelsInWriteArrays, minDirty, maxDirty);
|
||||
|
||||
printLog("stats: total %ld, leaves %ld, dirty %ld, colored %ld, shouldRender %ld, inVBO %ld\n",
|
||||
printLog("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",
|
||||
args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes);
|
||||
|
||||
printLog("inVBO %ld, nodesInVBOOverExpectedMax %ld, duplicateVBOIndex %ld, nodesInVBONotShouldRender %ld\n",
|
||||
printLog(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
|
||||
_voxelsInWriteArrays, minDirty, maxDirty);
|
||||
|
||||
printLog(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n",
|
||||
args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender);
|
||||
|
||||
glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;
|
||||
|
@ -1107,7 +1108,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
|||
}
|
||||
}
|
||||
|
||||
printLog("minInVBO=%ld maxInVBO=%ld _voxelsInWriteArrays=%ld _voxelsInReadArrays=%ld\n",
|
||||
printLog(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
|
||||
minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays);
|
||||
|
||||
}
|
||||
|
@ -1161,6 +1162,7 @@ void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* dest
|
|||
struct FalseColorizeOccludedArgs {
|
||||
ViewFrustum* viewFrustum;
|
||||
CoverageMap* map;
|
||||
CoverageMapV2* mapV2;
|
||||
VoxelTree* tree;
|
||||
long totalVoxels;
|
||||
long coloredVoxels;
|
||||
|
@ -1180,9 +1182,11 @@ struct FalseColorizeSubTreeOperationArgs {
|
|||
};
|
||||
|
||||
bool VoxelSystem::falseColorizeSubTreeOperation(VoxelNode* node, void* extraData) {
|
||||
FalseColorizeSubTreeOperationArgs* args = (FalseColorizeSubTreeOperationArgs*) extraData;
|
||||
node->setFalseColor(args->color[0], args->color[1], args->color[2]);
|
||||
args->voxelsTouched++;
|
||||
if (node->getShouldRender()) {
|
||||
FalseColorizeSubTreeOperationArgs* args = (FalseColorizeSubTreeOperationArgs*) extraData;
|
||||
node->setFalseColor(args->color[0], args->color[1], args->color[2]);
|
||||
args->voxelsTouched++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1262,12 +1266,143 @@ bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraDat
|
|||
}
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
void VoxelSystem::falseColorizeOccluded() {
|
||||
PerformanceWarning warn(true, "falseColorizeOccluded()",true);
|
||||
CoverageMap map;
|
||||
myCoverageMap.erase();
|
||||
|
||||
FalseColorizeOccludedArgs args;
|
||||
args.viewFrustum = Application::getInstance()->getViewFrustum();
|
||||
args.map = ↦
|
||||
args.map = &myCoverageMap;
|
||||
args.totalVoxels = 0;
|
||||
args.coloredVoxels = 0;
|
||||
args.occludedVoxels = 0;
|
||||
args.notOccludedVoxels = 0;
|
||||
args.outOfView = 0;
|
||||
args.subtreeVoxelsSkipped = 0;
|
||||
args.nonLeaves = 0;
|
||||
args.stagedForDeletion = 0;
|
||||
args.nonLeavesOutOfView = 0;
|
||||
args.nonLeavesOccluded = 0;
|
||||
args.tree = _tree;
|
||||
|
||||
VoxelProjectedPolygon::pointInside_calls = 0;
|
||||
VoxelProjectedPolygon::occludes_calls = 0;
|
||||
VoxelProjectedPolygon::intersects_calls = 0;
|
||||
|
||||
glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE);
|
||||
|
||||
_tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args);
|
||||
|
||||
printLog("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
position.x, position.y,
|
||||
args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
|
||||
args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
|
||||
args.stagedForDeletion,
|
||||
args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded,
|
||||
VoxelProjectedPolygon::pointInside_calls,
|
||||
VoxelProjectedPolygon::occludes_calls,
|
||||
VoxelProjectedPolygon::intersects_calls
|
||||
);
|
||||
|
||||
|
||||
//myCoverageMap.erase();
|
||||
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
bool VoxelSystem::falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData) {
|
||||
|
||||
FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData;
|
||||
args->totalVoxels++;
|
||||
|
||||
// if this node is staged for deletion, then just return
|
||||
if (node->isStagedForDeletion()) {
|
||||
args->stagedForDeletion++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we are a parent, let's see if we're completely occluded.
|
||||
if (!node->isLeaf()) {
|
||||
args->nonLeaves++;
|
||||
|
||||
AABox voxelBox = node->getAABox();
|
||||
voxelBox.scale(TREE_SCALE);
|
||||
VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox));
|
||||
|
||||
// If we're not all in view, then ignore it, and just return. But keep searching...
|
||||
if (!voxelPolygon->getAllInView()) {
|
||||
args->nonLeavesOutOfView++;
|
||||
delete voxelPolygon;
|
||||
return true;
|
||||
}
|
||||
|
||||
CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, false);
|
||||
if (result == V2_OCCLUDED) {
|
||||
args->nonLeavesOccluded++;
|
||||
delete voxelPolygon;
|
||||
|
||||
FalseColorizeSubTreeOperationArgs subArgs;
|
||||
subArgs.color[0] = 0;
|
||||
subArgs.color[1] = 255;
|
||||
subArgs.color[2] = 0;
|
||||
subArgs.voxelsTouched = 0;
|
||||
|
||||
args->tree->recurseNodeWithOperation(node, falseColorizeSubTreeOperation, &subArgs );
|
||||
|
||||
args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1);
|
||||
args->totalVoxels += (subArgs.voxelsTouched - 1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
delete voxelPolygon;
|
||||
return true; // keep looking...
|
||||
}
|
||||
|
||||
if (node->isLeaf() && node->isColored() && node->getShouldRender()) {
|
||||
args->coloredVoxels++;
|
||||
|
||||
AABox voxelBox = node->getAABox();
|
||||
voxelBox.scale(TREE_SCALE);
|
||||
VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox));
|
||||
|
||||
// If we're not all in view, then ignore it, and just return. But keep searching...
|
||||
if (!voxelPolygon->getAllInView()) {
|
||||
args->outOfView++;
|
||||
delete voxelPolygon;
|
||||
return true;
|
||||
}
|
||||
|
||||
CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, true);
|
||||
if (result == V2_OCCLUDED) {
|
||||
node->setFalseColor(255, 0, 0);
|
||||
args->occludedVoxels++;
|
||||
} else if (result == V2_STORED) {
|
||||
args->notOccludedVoxels++;
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
} else if (result == V2_DOESNT_FIT) {
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
}
|
||||
delete voxelPolygon; // V2 maps don't store polygons, so we're always in charge of freeing
|
||||
}
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
|
||||
void VoxelSystem::falseColorizeOccludedV2() {
|
||||
PerformanceWarning warn(true, "falseColorizeOccludedV2()",true);
|
||||
myCoverageMapV2.erase();
|
||||
|
||||
CoverageMapV2::wantDebugging = true;
|
||||
|
||||
VoxelProjectedPolygon::pointInside_calls = 0;
|
||||
VoxelProjectedPolygon::occludes_calls = 0;
|
||||
VoxelProjectedPolygon::intersects_calls = 0;
|
||||
|
||||
FalseColorizeOccludedArgs args;
|
||||
args.viewFrustum = Application::getInstance()->getViewFrustum();
|
||||
args.mapV2 = &myCoverageMapV2;
|
||||
args.totalVoxels = 0;
|
||||
args.coloredVoxels = 0;
|
||||
args.occludedVoxels = 0;
|
||||
|
@ -1282,15 +1417,22 @@ void VoxelSystem::falseColorizeOccluded() {
|
|||
|
||||
glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE);
|
||||
|
||||
_tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args);
|
||||
_tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedV2Operation, position, (void*)&args);
|
||||
|
||||
printLog("falseColorizeOccluded()\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n",
|
||||
printLog("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
position.x, position.y,
|
||||
args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
|
||||
args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
|
||||
args.stagedForDeletion,
|
||||
args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded);
|
||||
args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded,
|
||||
VoxelProjectedPolygon::pointInside_calls,
|
||||
VoxelProjectedPolygon::occludes_calls,
|
||||
VoxelProjectedPolygon::intersects_calls
|
||||
);
|
||||
//myCoverageMapV2.erase();
|
||||
|
||||
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,11 +11,15 @@
|
|||
|
||||
#include "InterfaceConfig.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <UDPSocket.h>
|
||||
|
||||
#include <CoverageMapV2.h>
|
||||
#include <NodeData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <VoxelTree.h>
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
@ -57,6 +61,7 @@ public:
|
|||
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||
void falseColorizeRandomEveryOther();
|
||||
void falseColorizeOccluded();
|
||||
void falseColorizeOccludedV2();
|
||||
|
||||
void killLocalVoxels();
|
||||
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
|
||||
|
@ -84,6 +89,9 @@ public:
|
|||
|
||||
void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot);
|
||||
void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode);
|
||||
|
||||
CoverageMapV2 myCoverageMapV2;
|
||||
CoverageMap myCoverageMap;
|
||||
|
||||
protected:
|
||||
float _treeScale;
|
||||
|
@ -123,6 +131,8 @@ private:
|
|||
static bool collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData);
|
||||
static bool falseColorizeOccludedOperation(VoxelNode* node, void* extraData);
|
||||
static bool falseColorizeSubTreeOperation(VoxelNode* node, void* extraData);
|
||||
static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData);
|
||||
|
||||
|
||||
int updateNodeInArraysAsFullVBO(VoxelNode* node);
|
||||
int updateNodeInArraysAsPartialVBO(VoxelNode* node);
|
||||
|
@ -150,10 +160,10 @@ private:
|
|||
bool _writeRenderFullVBO;
|
||||
bool _readRenderFullVBO;
|
||||
|
||||
double _setupNewVoxelsForDrawingLastElapsed;
|
||||
double _setupNewVoxelsForDrawingLastFinished;
|
||||
double _lastViewCulling;
|
||||
double _lastViewCullingElapsed;
|
||||
int _setupNewVoxelsForDrawingLastElapsed;
|
||||
uint64_t _setupNewVoxelsForDrawingLastFinished;
|
||||
uint64_t _lastViewCulling;
|
||||
int _lastViewCullingElapsed;
|
||||
|
||||
GLuint _vboVerticesID;
|
||||
GLuint _vboNormalsID;
|
||||
|
|
|
@ -21,11 +21,16 @@
|
|||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// register OpenCV matrix type with Qt metatype system
|
||||
#ifdef HAVE_OPENNI
|
||||
using namespace xn;
|
||||
#endif
|
||||
|
||||
// register types with Qt metatype system
|
||||
int jointVectorMetaType = qRegisterMetaType<JointVector>("JointVector");
|
||||
int matMetaType = qRegisterMetaType<Mat>("cv::Mat");
|
||||
int rotatedRectMetaType = qRegisterMetaType<RotatedRect>("cv::RotatedRect");
|
||||
|
||||
Webcam::Webcam() : _enabled(false), _active(false), _frameTextureID(0) {
|
||||
Webcam::Webcam() : _enabled(false), _active(false), _frameTextureID(0), _depthTextureID(0) {
|
||||
// the grabber simply runs as fast as possible
|
||||
_grabber = new FrameGrabber();
|
||||
_grabber->moveToThread(&_grabberThread);
|
||||
|
@ -79,9 +84,45 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
|||
glTexCoord2f(0, 1);
|
||||
glVertex2f(left, top + PREVIEW_HEIGHT);
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (_depthTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glBegin(GL_QUADS);
|
||||
int depthPreviewWidth = _depthWidth * PREVIEW_HEIGHT / _depthHeight;
|
||||
int depthLeft = screenWidth - depthPreviewWidth - 10;
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(depthLeft, top - PREVIEW_HEIGHT);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(depthLeft + depthPreviewWidth, top - PREVIEW_HEIGHT);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(depthLeft + depthPreviewWidth, top);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(depthLeft, top);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (!_joints.isEmpty()) {
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glPointSize(4.0f);
|
||||
glBegin(GL_POINTS);
|
||||
float projectedScale = PREVIEW_HEIGHT / (float)_depthHeight;
|
||||
foreach (const Joint& joint, _joints) {
|
||||
if (joint.isValid) {
|
||||
glVertex2f(depthLeft + joint.projected.x * projectedScale,
|
||||
top - PREVIEW_HEIGHT + joint.projected.y * projectedScale);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
Point2f facePoints[4];
|
||||
_faceRect.points(facePoints);
|
||||
|
@ -107,32 +148,51 @@ Webcam::~Webcam() {
|
|||
delete _grabber;
|
||||
}
|
||||
|
||||
void Webcam::setFrame(const Mat& frame, const RotatedRect& faceRect) {
|
||||
void Webcam::setFrame(const Mat& frame, int format, const Mat& depth, const RotatedRect& faceRect, const JointVector& joints) {
|
||||
IplImage image = frame;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.widthStep / 3);
|
||||
if (_frameTextureID == 0) {
|
||||
glGenTextures(1, &_frameTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _frameWidth = image.width, _frameHeight = image.height, 0, GL_BGR,
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _frameWidth = image.width, _frameHeight = image.height, 0, format,
|
||||
GL_UNSIGNED_BYTE, image.imageData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
printLog("Capturing webcam at %dx%d.\n", _frameWidth, _frameHeight);
|
||||
printLog("Capturing video at %dx%d.\n", _frameWidth, _frameHeight);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _frameWidth, _frameHeight, GL_BGR, GL_UNSIGNED_BYTE, image.imageData);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _frameWidth, _frameHeight, format, GL_UNSIGNED_BYTE, image.imageData);
|
||||
}
|
||||
|
||||
if (!depth.empty()) {
|
||||
IplImage depthImage = depth;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, depthImage.widthStep);
|
||||
if (_depthTextureID == 0) {
|
||||
glGenTextures(1, &_depthTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _depthWidth = depthImage.width, _depthHeight = depthImage.height, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, depthImage.imageData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
printLog("Capturing depth at %dx%d.\n", _depthWidth, _depthHeight);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _depthWidth, _depthHeight, GL_LUMINANCE,
|
||||
GL_UNSIGNED_BYTE, depthImage.imageData);
|
||||
}
|
||||
}
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// store our face rect, update our frame count for fps computation
|
||||
// store our face rect and joints, update our frame count for fps computation
|
||||
_faceRect = faceRect;
|
||||
_joints = joints;
|
||||
_frameCount++;
|
||||
|
||||
const int MAX_FPS = 60;
|
||||
const int MIN_FRAME_DELAY = 1000000 / MAX_FPS;
|
||||
long long now = usecTimestampNow();
|
||||
long long remaining = MIN_FRAME_DELAY;
|
||||
uint64_t now = usecTimestampNow();
|
||||
int remaining = MIN_FRAME_DELAY;
|
||||
if (_startTimestamp == 0) {
|
||||
_startTimestamp = now;
|
||||
} else {
|
||||
|
@ -140,33 +200,60 @@ void Webcam::setFrame(const Mat& frame, const RotatedRect& faceRect) {
|
|||
}
|
||||
_lastFrameTimestamp = now;
|
||||
|
||||
// roll is just the angle of the face rect (correcting for 180 degree rotations)
|
||||
float roll = faceRect.angle;
|
||||
if (roll < -90.0f) {
|
||||
roll += 180.0f;
|
||||
// see if we have joint data
|
||||
if (!_joints.isEmpty()) {
|
||||
_estimatedJoints.resize(NUM_AVATAR_JOINTS);
|
||||
glm::vec3 origin;
|
||||
if (_joints[AVATAR_JOINT_LEFT_HIP].isValid && _joints[AVATAR_JOINT_RIGHT_HIP].isValid) {
|
||||
origin = glm::mix(_joints[AVATAR_JOINT_LEFT_HIP].position, _joints[AVATAR_JOINT_RIGHT_HIP].position, 0.5f);
|
||||
|
||||
} else if (_joints[AVATAR_JOINT_TORSO].isValid) {
|
||||
const glm::vec3 TORSO_TO_PELVIS = glm::vec3(0.0f, -0.09f, -0.01f);
|
||||
origin = _joints[AVATAR_JOINT_TORSO].position + TORSO_TO_PELVIS;
|
||||
}
|
||||
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
|
||||
if (!_joints[i].isValid) {
|
||||
continue;
|
||||
}
|
||||
const float JOINT_SMOOTHING = 0.9f;
|
||||
_estimatedJoints[i].isValid = true;
|
||||
_estimatedJoints[i].position = glm::mix(_joints[i].position - origin,
|
||||
_estimatedJoints[i].position, JOINT_SMOOTHING);
|
||||
_estimatedJoints[i].rotation = safeMix(_joints[i].rotation,
|
||||
_estimatedJoints[i].rotation, JOINT_SMOOTHING);
|
||||
}
|
||||
_estimatedRotation = safeEulerAngles(_estimatedJoints[AVATAR_JOINT_HEAD_BASE].rotation);
|
||||
_estimatedPosition = _estimatedJoints[AVATAR_JOINT_HEAD_BASE].position;
|
||||
|
||||
} else if (roll > 90.0f) {
|
||||
roll -= 180.0f;
|
||||
}
|
||||
const float ROTATION_SMOOTHING = 0.95f;
|
||||
_estimatedRotation.z = glm::mix(roll, _estimatedRotation.z, ROTATION_SMOOTHING);
|
||||
|
||||
// determine position based on translation and scaling of the face rect
|
||||
if (_initialFaceRect.size.area() == 0) {
|
||||
_initialFaceRect = faceRect;
|
||||
_estimatedPosition = glm::vec3();
|
||||
|
||||
} else {
|
||||
float proportion = sqrtf(_initialFaceRect.size.area() / (float)faceRect.size.area());
|
||||
const float DISTANCE_TO_CAMERA = 0.333f;
|
||||
const float POSITION_SCALE = 0.5f;
|
||||
float z = DISTANCE_TO_CAMERA * proportion - DISTANCE_TO_CAMERA;
|
||||
glm::vec3 position = glm::vec3(
|
||||
(faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _frameWidth,
|
||||
(faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _frameWidth,
|
||||
z);
|
||||
const float POSITION_SMOOTHING = 0.95f;
|
||||
_estimatedPosition = glm::mix(position, _estimatedPosition, POSITION_SMOOTHING);
|
||||
// roll is just the angle of the face rect (correcting for 180 degree rotations)
|
||||
float roll = faceRect.angle;
|
||||
if (roll < -90.0f) {
|
||||
roll += 180.0f;
|
||||
|
||||
} else if (roll > 90.0f) {
|
||||
roll -= 180.0f;
|
||||
}
|
||||
const float ROTATION_SMOOTHING = 0.95f;
|
||||
_estimatedRotation.z = glm::mix(roll, _estimatedRotation.z, ROTATION_SMOOTHING);
|
||||
|
||||
// determine position based on translation and scaling of the face rect
|
||||
if (_initialFaceRect.size.area() == 0) {
|
||||
_initialFaceRect = faceRect;
|
||||
_estimatedPosition = glm::vec3();
|
||||
|
||||
} else {
|
||||
float proportion = sqrtf(_initialFaceRect.size.area() / (float)faceRect.size.area());
|
||||
const float DISTANCE_TO_CAMERA = 0.333f;
|
||||
const float POSITION_SCALE = 0.5f;
|
||||
float z = DISTANCE_TO_CAMERA * proportion - DISTANCE_TO_CAMERA;
|
||||
glm::vec3 position = glm::vec3(
|
||||
(faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _frameWidth,
|
||||
(faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _frameWidth,
|
||||
z);
|
||||
const float POSITION_SMOOTHING = 0.95f;
|
||||
_estimatedPosition = glm::mix(position, _estimatedPosition, POSITION_SMOOTHING);
|
||||
}
|
||||
}
|
||||
|
||||
// note that we have data
|
||||
|
@ -176,7 +263,7 @@ void Webcam::setFrame(const Mat& frame, const RotatedRect& faceRect) {
|
|||
QTimer::singleShot(qMax((int)remaining / 1000, 0), _grabber, SLOT(grabFrame()));
|
||||
}
|
||||
|
||||
FrameGrabber::FrameGrabber() : _capture(0), _searchWindow(0, 0, 0, 0) {
|
||||
FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0, 0, 0, 0) {
|
||||
}
|
||||
|
||||
FrameGrabber::~FrameGrabber() {
|
||||
|
@ -185,52 +272,170 @@ FrameGrabber::~FrameGrabber() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
static AvatarJointID xnToAvatarJoint(XnSkeletonJoint joint) {
|
||||
switch (joint) {
|
||||
case XN_SKEL_HEAD: return AVATAR_JOINT_HEAD_TOP;
|
||||
case XN_SKEL_NECK: return AVATAR_JOINT_HEAD_BASE;
|
||||
case XN_SKEL_TORSO: return AVATAR_JOINT_CHEST;
|
||||
|
||||
case XN_SKEL_LEFT_SHOULDER: return AVATAR_JOINT_RIGHT_ELBOW;
|
||||
case XN_SKEL_LEFT_ELBOW: return AVATAR_JOINT_RIGHT_WRIST;
|
||||
|
||||
case XN_SKEL_RIGHT_SHOULDER: return AVATAR_JOINT_LEFT_ELBOW;
|
||||
case XN_SKEL_RIGHT_ELBOW: return AVATAR_JOINT_LEFT_WRIST;
|
||||
|
||||
case XN_SKEL_LEFT_HIP: return AVATAR_JOINT_RIGHT_KNEE;
|
||||
case XN_SKEL_LEFT_KNEE: return AVATAR_JOINT_RIGHT_HEEL;
|
||||
case XN_SKEL_LEFT_FOOT: return AVATAR_JOINT_RIGHT_TOES;
|
||||
|
||||
case XN_SKEL_RIGHT_HIP: return AVATAR_JOINT_LEFT_KNEE;
|
||||
case XN_SKEL_RIGHT_KNEE: return AVATAR_JOINT_LEFT_HEEL;
|
||||
case XN_SKEL_RIGHT_FOOT: return AVATAR_JOINT_LEFT_TOES;
|
||||
|
||||
default: return AVATAR_JOINT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int getParentJoint(XnSkeletonJoint joint) {
|
||||
switch (joint) {
|
||||
case XN_SKEL_HEAD: return XN_SKEL_NECK;
|
||||
case XN_SKEL_TORSO: return -1;
|
||||
|
||||
case XN_SKEL_LEFT_ELBOW: return XN_SKEL_LEFT_SHOULDER;
|
||||
case XN_SKEL_LEFT_HAND: return XN_SKEL_LEFT_ELBOW;
|
||||
|
||||
case XN_SKEL_RIGHT_ELBOW: return XN_SKEL_RIGHT_SHOULDER;
|
||||
case XN_SKEL_RIGHT_HAND: return XN_SKEL_RIGHT_ELBOW;
|
||||
|
||||
case XN_SKEL_LEFT_KNEE: return XN_SKEL_LEFT_HIP;
|
||||
case XN_SKEL_LEFT_FOOT: return XN_SKEL_LEFT_KNEE;
|
||||
|
||||
case XN_SKEL_RIGHT_KNEE: return XN_SKEL_RIGHT_HIP;
|
||||
case XN_SKEL_RIGHT_FOOT: return XN_SKEL_RIGHT_KNEE;
|
||||
|
||||
default: return XN_SKEL_TORSO;
|
||||
}
|
||||
}
|
||||
|
||||
static glm::vec3 xnToGLM(const XnVector3D& vector, bool flip = false) {
|
||||
return glm::vec3(vector.X * (flip ? -1 : 1), vector.Y, vector.Z);
|
||||
}
|
||||
|
||||
static glm::quat xnToGLM(const XnMatrix3X3& matrix) {
|
||||
glm::quat rotation = glm::quat_cast(glm::mat3(
|
||||
matrix.elements[0], matrix.elements[1], matrix.elements[2],
|
||||
matrix.elements[3], matrix.elements[4], matrix.elements[5],
|
||||
matrix.elements[6], matrix.elements[7], matrix.elements[8]));
|
||||
return glm::quat(rotation.w, -rotation.x, rotation.y, rotation.z);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE newUser(UserGenerator& generator, XnUserID id, void* cookie) {
|
||||
printLog("Found user %d.\n", id);
|
||||
generator.GetSkeletonCap().RequestCalibration(id, false);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE lostUser(UserGenerator& generator, XnUserID id, void* cookie) {
|
||||
printLog("Lost user %d.\n", id);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE calibrationStarted(SkeletonCapability& capability, XnUserID id, void* cookie) {
|
||||
printLog("Calibration started for user %d.\n", id);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE calibrationCompleted(SkeletonCapability& capability,
|
||||
XnUserID id, XnCalibrationStatus status, void* cookie) {
|
||||
if (status == XN_CALIBRATION_STATUS_OK) {
|
||||
printLog("Calibration completed for user %d.\n", id);
|
||||
capability.StartTracking(id);
|
||||
|
||||
} else {
|
||||
printLog("Calibration failed to user %d.\n", id);
|
||||
capability.RequestCalibration(id, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void FrameGrabber::reset() {
|
||||
_searchWindow = cv::Rect(0, 0, 0, 0);
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
if (_userGenerator.IsValid() && _userGenerator.GetSkeletonCap().IsTracking(_userID)) {
|
||||
_userGenerator.GetSkeletonCap().RequestCalibration(_userID, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FrameGrabber::grabFrame() {
|
||||
if (_capture == 0) {
|
||||
if ((_capture = cvCaptureFromCAM(-1)) == 0) {
|
||||
printLog("Failed to open webcam.\n");
|
||||
return;
|
||||
}
|
||||
const int IDEAL_FRAME_WIDTH = 320;
|
||||
const int IDEAL_FRAME_HEIGHT = 240;
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH, IDEAL_FRAME_WIDTH);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT, IDEAL_FRAME_HEIGHT);
|
||||
if (!(_initialized || init())) {
|
||||
return;
|
||||
}
|
||||
int format = GL_BGR;
|
||||
Mat frame;
|
||||
JointVector joints;
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
if (_depthGenerator.IsValid()) {
|
||||
_xnContext.WaitAnyUpdateAll();
|
||||
frame = Mat(_imageMetaData.YRes(), _imageMetaData.XRes(), CV_8UC3, (void*)_imageGenerator.GetImageMap());
|
||||
format = GL_RGB;
|
||||
|
||||
#ifdef __APPLE__
|
||||
configureCamera(0x5ac, 0x8510, false, 0.975, 0.5, 1.0, 0.5, true, 0.5);
|
||||
#else
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_EXPOSURE, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_CONTRAST, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_SATURATION, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_BRIGHTNESS, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_HUE, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_GAIN, 0.5);
|
||||
#endif
|
||||
|
||||
switchToResourcesParentIfRequired();
|
||||
if (!_faceCascade.load("resources/haarcascades/haarcascade_frontalface_alt.xml")) {
|
||||
printLog("Failed to load Haar cascade for face tracking.\n");
|
||||
Mat depth = Mat(_depthMetaData.YRes(), _depthMetaData.XRes(), CV_16UC1, (void*)_depthGenerator.GetDepthMap());
|
||||
const double EIGHT_BIT_MAX = 255;
|
||||
const double ELEVEN_BIT_MAX = 2047;
|
||||
depth.convertTo(_grayDepthFrame, CV_8UC1, EIGHT_BIT_MAX / ELEVEN_BIT_MAX);
|
||||
|
||||
_userID = 0;
|
||||
XnUInt16 userCount = 1;
|
||||
_userGenerator.GetUsers(&_userID, userCount);
|
||||
if (userCount > 0 && _userGenerator.GetSkeletonCap().IsTracking(_userID)) {
|
||||
joints.resize(NUM_AVATAR_JOINTS);
|
||||
const int MAX_ACTIVE_JOINTS = 16;
|
||||
XnSkeletonJoint activeJoints[MAX_ACTIVE_JOINTS];
|
||||
XnUInt16 activeJointCount = MAX_ACTIVE_JOINTS;
|
||||
_userGenerator.GetSkeletonCap().EnumerateActiveJoints(activeJoints, activeJointCount);
|
||||
XnSkeletonJointTransformation transform;
|
||||
for (int i = 0; i < activeJointCount; i++) {
|
||||
AvatarJointID avatarJoint = xnToAvatarJoint(activeJoints[i]);
|
||||
if (avatarJoint == AVATAR_JOINT_NULL) {
|
||||
continue;
|
||||
}
|
||||
_userGenerator.GetSkeletonCap().GetSkeletonJoint(_userID, activeJoints[i], transform);
|
||||
XnVector3D projected;
|
||||
_depthGenerator.ConvertRealWorldToProjective(1, &transform.position.position, &projected);
|
||||
glm::quat rotation = xnToGLM(transform.orientation.orientation);
|
||||
int parentJoint = getParentJoint(activeJoints[i]);
|
||||
if (parentJoint != -1) {
|
||||
XnSkeletonJointOrientation parentOrientation;
|
||||
_userGenerator.GetSkeletonCap().GetSkeletonJointOrientation(
|
||||
_userID, (XnSkeletonJoint)parentJoint, parentOrientation);
|
||||
rotation = glm::inverse(xnToGLM(parentOrientation.orientation)) * rotation;
|
||||
}
|
||||
const float METERS_PER_MM = 1.0f / 1000.0f;
|
||||
joints[avatarJoint] = Joint(xnToGLM(transform.position.position, true) * METERS_PER_MM,
|
||||
rotation, xnToGLM(projected));
|
||||
}
|
||||
}
|
||||
}
|
||||
IplImage* image = cvQueryFrame(_capture);
|
||||
if (image == 0) {
|
||||
// try again later
|
||||
QMetaObject::invokeMethod(this, "grabFrame", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
// make sure it's in the format we expect
|
||||
if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U || image->dataOrder != IPL_DATA_ORDER_PIXEL ||
|
||||
image->origin != 0) {
|
||||
printLog("Invalid webcam image format.\n");
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (frame.empty()) {
|
||||
IplImage* image = cvQueryFrame(_capture);
|
||||
if (image == 0) {
|
||||
// try again later
|
||||
QMetaObject::invokeMethod(this, "grabFrame", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
// make sure it's in the format we expect
|
||||
if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U || image->dataOrder != IPL_DATA_ORDER_PIXEL ||
|
||||
image->origin != 0) {
|
||||
printLog("Invalid webcam image format.\n");
|
||||
return;
|
||||
}
|
||||
frame = image;
|
||||
}
|
||||
|
||||
// if we don't have a search window (yet), try using the face cascade
|
||||
Mat frame = image;
|
||||
int channels = 0;
|
||||
float ranges[] = { 0, 180 };
|
||||
const float* range = ranges;
|
||||
|
@ -239,7 +444,7 @@ void FrameGrabber::grabFrame() {
|
|||
_faceCascade.detectMultiScale(frame, faces, 1.1, 6);
|
||||
if (!faces.empty()) {
|
||||
_searchWindow = faces.front();
|
||||
updateHSVFrame(frame);
|
||||
updateHSVFrame(frame, format);
|
||||
|
||||
Mat faceHsv(_hsvFrame, _searchWindow);
|
||||
Mat faceMask(_mask, _searchWindow);
|
||||
|
@ -252,7 +457,7 @@ void FrameGrabber::grabFrame() {
|
|||
}
|
||||
RotatedRect faceRect;
|
||||
if (_searchWindow.area() > 0) {
|
||||
updateHSVFrame(frame);
|
||||
updateHSVFrame(frame, format);
|
||||
|
||||
calcBackProject(&_hsvFrame, 1, &channels, _histogram, _backProject, &range);
|
||||
bitwise_and(_backProject, _mask, _backProject);
|
||||
|
@ -261,10 +466,74 @@ void FrameGrabber::grabFrame() {
|
|||
_searchWindow = faceRect.boundingRect();
|
||||
}
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
||||
Q_ARG(cv::Mat, frame), Q_ARG(cv::RotatedRect, faceRect));
|
||||
Q_ARG(cv::Mat, frame), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame),
|
||||
Q_ARG(cv::RotatedRect, faceRect), Q_ARG(JointVector, joints));
|
||||
}
|
||||
|
||||
void FrameGrabber::updateHSVFrame(const Mat& frame) {
|
||||
cvtColor(frame, _hsvFrame, CV_BGR2HSV);
|
||||
bool FrameGrabber::init() {
|
||||
_initialized = true;
|
||||
|
||||
// load our face cascade
|
||||
switchToResourcesParentIfRequired();
|
||||
if (!_faceCascade.load("resources/haarcascades/haarcascade_frontalface_alt.xml")) {
|
||||
printLog("Failed to load Haar cascade for face tracking.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// first try for a Kinect
|
||||
#ifdef HAVE_OPENNI
|
||||
_xnContext.Init();
|
||||
if (_depthGenerator.Create(_xnContext) == XN_STATUS_OK && _imageGenerator.Create(_xnContext) == XN_STATUS_OK &&
|
||||
_userGenerator.Create(_xnContext) == XN_STATUS_OK &&
|
||||
_userGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON)) {
|
||||
_depthGenerator.GetMetaData(_depthMetaData);
|
||||
_imageGenerator.SetPixelFormat(XN_PIXEL_FORMAT_RGB24);
|
||||
_imageGenerator.GetMetaData(_imageMetaData);
|
||||
|
||||
XnCallbackHandle userCallbacks, calibrationStartCallback, calibrationCompleteCallback;
|
||||
_userGenerator.RegisterUserCallbacks(newUser, lostUser, 0, userCallbacks);
|
||||
_userGenerator.GetSkeletonCap().RegisterToCalibrationStart(calibrationStarted, 0, calibrationStartCallback);
|
||||
_userGenerator.GetSkeletonCap().RegisterToCalibrationComplete(calibrationCompleted, 0, calibrationCompleteCallback);
|
||||
|
||||
_userGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_UPPER);
|
||||
|
||||
_xnContext.StartGeneratingAll();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// next, an ordinary webcam
|
||||
if ((_capture = cvCaptureFromCAM(-1)) == 0) {
|
||||
printLog("Failed to open webcam.\n");
|
||||
return false;
|
||||
}
|
||||
const int IDEAL_FRAME_WIDTH = 320;
|
||||
const int IDEAL_FRAME_HEIGHT = 240;
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH, IDEAL_FRAME_WIDTH);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT, IDEAL_FRAME_HEIGHT);
|
||||
|
||||
#ifdef __APPLE__
|
||||
configureCamera(0x5ac, 0x8510, false, 0.975, 0.5, 1.0, 0.5, true, 0.5);
|
||||
#else
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_EXPOSURE, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_CONTRAST, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_SATURATION, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_BRIGHTNESS, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_HUE, 0.5);
|
||||
cvSetCaptureProperty(_capture, CV_CAP_PROP_GAIN, 0.5);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameGrabber::updateHSVFrame(const Mat& frame, int format) {
|
||||
cvtColor(frame, _hsvFrame, format == GL_RGB ? CV_RGB2HSV : CV_BGR2HSV);
|
||||
inRange(_hsvFrame, Scalar(0, 55, 65), Scalar(180, 256, 256), _mask);
|
||||
}
|
||||
|
||||
Joint::Joint(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& projected) :
|
||||
isValid(true), position(position), rotation(rotation), projected(projected) {
|
||||
}
|
||||
|
||||
Joint::Joint() : isValid(false) {
|
||||
}
|
||||
|
|
|
@ -12,11 +12,17 @@
|
|||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
#include <XnCppWrapper.h>
|
||||
#endif
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class QImage;
|
||||
|
@ -24,6 +30,9 @@ class QImage;
|
|||
struct CvCapture;
|
||||
|
||||
class FrameGrabber;
|
||||
class Joint;
|
||||
|
||||
typedef QVector<Joint> JointVector;
|
||||
|
||||
class Webcam : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -36,6 +45,7 @@ public:
|
|||
const bool isActive() const { return _active; }
|
||||
const glm::vec3& getEstimatedPosition() const { return _estimatedPosition; }
|
||||
const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }
|
||||
const JointVector& getEstimatedJoints() const { return _estimatedJoints; }
|
||||
|
||||
void reset();
|
||||
void renderPreview(int screenWidth, int screenHeight);
|
||||
|
@ -43,7 +53,8 @@ public:
|
|||
public slots:
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setFrame(const cv::Mat& image, const cv::RotatedRect& faceRect);
|
||||
void setFrame(const cv::Mat& video, int format, const cv::Mat& depth,
|
||||
const cv::RotatedRect& faceRect, const JointVector& joints);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -54,17 +65,22 @@ private:
|
|||
bool _active;
|
||||
int _frameWidth;
|
||||
int _frameHeight;
|
||||
int _depthWidth;
|
||||
int _depthHeight;
|
||||
GLuint _frameTextureID;
|
||||
GLuint _depthTextureID;
|
||||
cv::RotatedRect _faceRect;
|
||||
cv::RotatedRect _initialFaceRect;
|
||||
JointVector _joints;
|
||||
|
||||
long long _startTimestamp;
|
||||
uint64_t _startTimestamp;
|
||||
int _frameCount;
|
||||
|
||||
long long _lastFrameTimestamp;
|
||||
uint64_t _lastFrameTimestamp;
|
||||
|
||||
glm::vec3 _estimatedPosition;
|
||||
glm::vec3 _estimatedRotation;
|
||||
JointVector _estimatedJoints;
|
||||
};
|
||||
|
||||
class FrameGrabber : public QObject {
|
||||
|
@ -82,8 +98,10 @@ public slots:
|
|||
|
||||
private:
|
||||
|
||||
void updateHSVFrame(const cv::Mat& frame);
|
||||
bool init();
|
||||
void updateHSVFrame(const cv::Mat& frame, int format);
|
||||
|
||||
bool _initialized;
|
||||
CvCapture* _capture;
|
||||
cv::CascadeClassifier _faceCascade;
|
||||
cv::Mat _hsvFrame;
|
||||
|
@ -91,8 +109,32 @@ private:
|
|||
cv::SparseMat _histogram;
|
||||
cv::Mat _backProject;
|
||||
cv::Rect _searchWindow;
|
||||
cv::Mat _grayDepthFrame;
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
xn::Context _xnContext;
|
||||
xn::DepthGenerator _depthGenerator;
|
||||
xn::ImageGenerator _imageGenerator;
|
||||
xn::UserGenerator _userGenerator;
|
||||
xn::DepthMetaData _depthMetaData;
|
||||
xn::ImageMetaData _imageMetaData;
|
||||
XnUserID _userID;
|
||||
#endif
|
||||
};
|
||||
|
||||
class Joint {
|
||||
public:
|
||||
|
||||
Joint(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& projected);
|
||||
Joint();
|
||||
|
||||
bool isValid;
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
glm::vec3 projected;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(JointVector)
|
||||
Q_DECLARE_METATYPE(cv::Mat)
|
||||
Q_DECLARE_METATYPE(cv::RotatedRect)
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
|
|||
|
||||
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
|
||||
|
||||
long long usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
||||
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ const int STREAM_IDENTIFIER_NUM_BYTES = 8;
|
|||
|
||||
const int MAX_INJECTOR_VOLUME = 0xFF;
|
||||
|
||||
const long long INJECT_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
||||
const int INJECT_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
||||
|
||||
class AudioInjector {
|
||||
public:
|
||||
|
|
|
@ -32,10 +32,9 @@ AvatarData::AvatarData(Node* owningNode) :
|
|||
_cameraNearClip(0.0f),
|
||||
_cameraFarClip(0.0f),
|
||||
_keyState(NO_KEY_DOWN),
|
||||
_wantResIn(false),
|
||||
_wantColor(true),
|
||||
_wantDelta(false),
|
||||
_wantOcclusionCulling(false),
|
||||
_wantOcclusionCulling(true),
|
||||
_headData(NULL),
|
||||
_handData(NULL)
|
||||
{
|
||||
|
@ -113,7 +112,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
|
||||
// bitMask of less than byte wide items
|
||||
unsigned char bitItems = 0;
|
||||
if (_wantResIn) { setAtBit(bitItems, WANT_RESIN_AT_BIT); }
|
||||
if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); }
|
||||
if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); }
|
||||
if (_wantOcclusionCulling) { setAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); }
|
||||
|
@ -152,6 +150,13 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
}
|
||||
}
|
||||
|
||||
// skeleton joints
|
||||
*destinationBuffer++ = (unsigned char)_joints.size();
|
||||
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
|
||||
*destinationBuffer++ = (unsigned char)it->jointID;
|
||||
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, it->rotation);
|
||||
}
|
||||
|
||||
return destinationBuffer - bufferStart;
|
||||
}
|
||||
|
||||
|
@ -234,7 +239,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
// voxel sending features...
|
||||
unsigned char bitItems = 0;
|
||||
bitItems = (unsigned char)*sourceBuffer++;
|
||||
_wantResIn = oneAtBit(bitItems, WANT_RESIN_AT_BIT);
|
||||
_wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT);
|
||||
_wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT);
|
||||
_wantOcclusionCulling = oneAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT);
|
||||
|
@ -264,6 +268,16 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
_handData->setFingerRoots(fingerRoots);
|
||||
}
|
||||
|
||||
// skeleton joints
|
||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
||||
{
|
||||
_joints.resize(*sourceBuffer++);
|
||||
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
|
||||
it->jointID = *sourceBuffer++;
|
||||
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, it->rotation);
|
||||
}
|
||||
}
|
||||
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
@ -19,7 +20,7 @@
|
|||
#include "HeadData.h"
|
||||
#include "HandData.h"
|
||||
|
||||
const int WANT_RESIN_AT_BIT = 0;
|
||||
const int UNUSED_BIT = 0; // this bit is available to use
|
||||
const int WANT_COLOR_AT_BIT = 1;
|
||||
const int WANT_DELTA_AT_BIT = 2;
|
||||
const int KEY_STATE_START_BIT = 3; // 4th and 5th bits
|
||||
|
@ -36,6 +37,8 @@ enum KeyState
|
|||
DELETE_KEY_DOWN
|
||||
};
|
||||
|
||||
class JointData;
|
||||
|
||||
class AvatarData : public NodeData {
|
||||
public:
|
||||
AvatarData(Node* owningNode = NULL);
|
||||
|
@ -88,11 +91,9 @@ public:
|
|||
const std::string& chatMessage () const { return _chatMessage; }
|
||||
|
||||
// related to Voxel Sending strategies
|
||||
bool getWantResIn() const { return _wantResIn; }
|
||||
bool getWantColor() const { return _wantColor; }
|
||||
bool getWantDelta() const { return _wantDelta; }
|
||||
bool getWantOcclusionCulling() const { return _wantOcclusionCulling; }
|
||||
void setWantResIn(bool wantResIn) { _wantResIn = wantResIn; }
|
||||
void setWantColor(bool wantColor) { _wantColor = wantColor; }
|
||||
void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; }
|
||||
void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; }
|
||||
|
@ -127,19 +128,27 @@ protected:
|
|||
std::string _chatMessage;
|
||||
|
||||
// voxel server sending items
|
||||
bool _wantResIn;
|
||||
bool _wantColor;
|
||||
bool _wantDelta;
|
||||
bool _wantOcclusionCulling;
|
||||
|
||||
std::vector<JointData> _joints;
|
||||
|
||||
HeadData* _headData;
|
||||
HandData* _handData;
|
||||
|
||||
private:
|
||||
// privatize the copy constructor and assignment operator so they cannot be called
|
||||
AvatarData(const AvatarData&);
|
||||
AvatarData& operator= (const AvatarData&);
|
||||
};
|
||||
|
||||
class JointData {
|
||||
public:
|
||||
|
||||
int jointID;
|
||||
glm::quat rotation;
|
||||
};
|
||||
|
||||
// These pack/unpack functions are designed to start specific known types in as efficient a manner
|
||||
// as possible. Taking advantage of the known characteristics of the semantic types.
|
||||
|
|
|
@ -37,11 +37,11 @@ public:
|
|||
uint16_t getNodeID() const { return _nodeID; }
|
||||
void setNodeID(uint16_t nodeID) { _nodeID = nodeID;}
|
||||
|
||||
long long getWakeMicrostamp() const { return _wakeMicrostamp; }
|
||||
void setWakeMicrostamp(long long wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; }
|
||||
uint64_t getWakeMicrostamp() const { return _wakeMicrostamp; }
|
||||
void setWakeMicrostamp(uint64_t wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; }
|
||||
|
||||
long long getLastHeardMicrostamp() const { return _lastHeardMicrostamp; }
|
||||
void setLastHeardMicrostamp(long long lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; }
|
||||
uint64_t getLastHeardMicrostamp() const { return _lastHeardMicrostamp; }
|
||||
void setLastHeardMicrostamp(uint64_t lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; }
|
||||
|
||||
sockaddr* getPublicSocket() const { return _publicSocket; }
|
||||
void setPublicSocket(sockaddr* publicSocket) { _publicSocket = publicSocket; }
|
||||
|
@ -74,8 +74,8 @@ private:
|
|||
|
||||
char _type;
|
||||
uint16_t _nodeID;
|
||||
long long _wakeMicrostamp;
|
||||
long long _lastHeardMicrostamp;
|
||||
uint64_t _wakeMicrostamp;
|
||||
uint64_t _lastHeardMicrostamp;
|
||||
sockaddr* _publicSocket;
|
||||
sockaddr* _localSocket;
|
||||
sockaddr* _activeSocket;
|
||||
|
|
|
@ -80,7 +80,9 @@ void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
|||
for(NodeList::iterator node = begin(); node != end(); node++) {
|
||||
if (socketMatch(node->getPublicSocket(), nodeAddress) ||
|
||||
socketMatch(node->getLocalSocket(), nodeAddress)) {
|
||||
int pingTime = usecTimestampNow() - *(long long *)(packetData + numBytesForPacketHeader(packetData));
|
||||
|
||||
int pingTime = usecTimestampNow() - *(uint64_t *)(packetData + numBytesForPacketHeader(packetData));
|
||||
|
||||
node->setPingMs(pingTime / 1000);
|
||||
break;
|
||||
}
|
||||
|
@ -411,7 +413,8 @@ Node* NodeList::soloNodeOfType(char nodeType) {
|
|||
|
||||
void *removeSilentNodes(void *args) {
|
||||
NodeList* nodeList = (NodeList*) args;
|
||||
long long checkTimeUSecs, sleepTime;
|
||||
uint64_t checkTimeUSecs;
|
||||
int sleepTime;
|
||||
|
||||
while (!silentNodeThreadStopFlag) {
|
||||
checkTimeUSecs = usecTimestampNow();
|
||||
|
|
|
@ -105,17 +105,17 @@ int PerfStat::DumpStats(char** array) {
|
|||
|
||||
// Destructor handles recording all of our stats
|
||||
PerformanceWarning::~PerformanceWarning() {
|
||||
long long end = usecTimestampNow();
|
||||
uint64_t end = usecTimestampNow();
|
||||
double elapsedmsec = (end - _start) / 1000.0;
|
||||
if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - _start) / 1000000.0;
|
||||
printLog("WARNING! %s took %lf seconds\n", _message, elapsedsec);
|
||||
printLog("%s%s took %lf seconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedsec);
|
||||
} else {
|
||||
printLog("WARNING! %s took %lf milliseconds\n", _message, elapsedmsec);
|
||||
printLog("%s%s took %lf milliseconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedmsec);
|
||||
}
|
||||
} else if (_alwaysDisplay) {
|
||||
printLog("WARNING! %s took %lf milliseconds\n", _message, elapsedmsec);
|
||||
printLog("%s took %lf milliseconds\n", _message, elapsedmsec);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef std::map<std::string,PerfStatHistory,std::less<std::string> >::iterator
|
|||
|
||||
class PerformanceWarning {
|
||||
private:
|
||||
long long _start;
|
||||
uint64_t _start;
|
||||
const char* _message;
|
||||
bool _renderWarningsOn;
|
||||
bool _alwaysDisplay;
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
long long usecTimestamp(timeval *time) {
|
||||
uint64_t usecTimestamp(timeval *time) {
|
||||
return (time->tv_sec * 1000000 + time->tv_usec);
|
||||
}
|
||||
|
||||
long long usecTimestampNow() {
|
||||
uint64_t usecTimestampNow() {
|
||||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (now.tv_sec * 1000000 + now.tv_usec);
|
||||
|
@ -445,3 +445,25 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex,
|
|||
return -1; // error case
|
||||
}
|
||||
|
||||
int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* originalIndexArray,
|
||||
int currentCount, int maxCount) {
|
||||
|
||||
int i = 0;
|
||||
if (currentCount > 0) {
|
||||
while (i < currentCount && value != valueArray[i]) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (value == valueArray[i] && i < currentCount) {
|
||||
// i is the location of the item we were looking for
|
||||
// shift array elements to the left
|
||||
memmove(&valueArray[i], &valueArray[i + 1], sizeof(void*) * ((currentCount-1) - i));
|
||||
memmove(&keyArray[i], &keyArray[i + 1], sizeof(float) * ((currentCount-1) - i));
|
||||
if (originalIndexArray) {
|
||||
memmove(&originalIndexArray[i], &originalIndexArray[i + 1], sizeof(int) * ((currentCount-1) - i));
|
||||
}
|
||||
return currentCount-1;
|
||||
}
|
||||
}
|
||||
return -1; // error case
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ static const float DECIMETER = 0.1f;
|
|||
static const float CENTIMETER = 0.01f;
|
||||
static const float MILLIIMETER = 0.001f;
|
||||
|
||||
long long usecTimestamp(timeval *time);
|
||||
long long usecTimestampNow();
|
||||
uint64_t usecTimestamp(timeval *time);
|
||||
uint64_t usecTimestampNow();
|
||||
|
||||
float randFloat();
|
||||
int randIntInRange (int min, int max);
|
||||
|
@ -88,6 +88,11 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex,
|
|||
void** valueArray, float* keyArray, int* originalIndexArray,
|
||||
int currentCount, int maxCount);
|
||||
|
||||
int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* originalIndexArray,
|
||||
int currentCount, int maxCount);
|
||||
|
||||
|
||||
|
||||
// Helper Class for debugging
|
||||
class debug {
|
||||
public:
|
||||
|
|
|
@ -22,7 +22,7 @@ int SimpleMovingAverage::updateAverage(float sample) {
|
|||
if (_numSamples > 0) {
|
||||
_average = (ONE_MINUS_WEIGHTING * _average) + (WEIGHTING * sample);
|
||||
|
||||
float eventDelta = (usecTimestampNow() - _lastEventTimestamp) / 1000000;
|
||||
float eventDelta = (usecTimestampNow() - _lastEventTimestamp) / 1000000.0f;
|
||||
|
||||
if (_numSamples > 1) {
|
||||
_eventDeltaAverage = (ONE_MINUS_WEIGHTING * _eventDeltaAverage) +
|
||||
|
@ -46,7 +46,7 @@ void SimpleMovingAverage::reset() {
|
|||
|
||||
float SimpleMovingAverage::getEventDeltaAverage() {
|
||||
return (ONE_MINUS_WEIGHTING * _eventDeltaAverage) +
|
||||
(WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000));
|
||||
(WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f));
|
||||
}
|
||||
|
||||
float SimpleMovingAverage::getAverageSampleValuePerSecond() {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef __hifi__Stats__
|
||||
#define __hifi__Stats__
|
||||
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
||||
class SimpleMovingAverage {
|
||||
public:
|
||||
|
@ -26,7 +26,7 @@ public:
|
|||
float getAverageSampleValuePerSecond();
|
||||
private:
|
||||
int _numSamples;
|
||||
long long _lastEventTimestamp;
|
||||
uint64_t _lastEventTimestamp;
|
||||
float _average;
|
||||
float _eventDeltaAverage;
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "StdDev.h"
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include "StdDev.h"
|
||||
|
||||
const int MAX_STDEV_SAMPLES = 1000;
|
||||
|
||||
|
@ -34,6 +35,16 @@ float StDev::getAverage() {
|
|||
return average/(float)sampleCount;
|
||||
else return 0;
|
||||
}
|
||||
/*
|
||||
float StDev::getMax() {
|
||||
float average = -FLT_MAX;
|
||||
for (int i = 0; i < sampleCount; i++) {
|
||||
average += data[i];
|
||||
}
|
||||
if (sampleCount > 0)
|
||||
return average/(float)sampleCount;
|
||||
else return 0;
|
||||
}*/
|
||||
|
||||
float StDev::getStDev() {
|
||||
float average = getAverage();
|
||||
|
|
|
@ -15,4 +15,9 @@ include(${MACRO_DIR}/IncludeGLM.cmake)
|
|||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
|
|
|
@ -13,9 +13,12 @@
|
|||
|
||||
int CoverageMap::_mapCount = 0;
|
||||
int CoverageMap::_checkMapRootCalls = 0;
|
||||
int CoverageMap::_notAllInView = 0;
|
||||
bool CoverageMap::wantDebugging = false;
|
||||
|
||||
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-2.f,-2.f), glm::vec2(4.f,4.f));
|
||||
const int MAX_POLYGONS_PER_REGION = 50;
|
||||
|
||||
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f));
|
||||
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
//
|
||||
|
@ -64,6 +67,22 @@ CoverageMap::~CoverageMap() {
|
|||
erase();
|
||||
};
|
||||
|
||||
void CoverageMap::printStats() {
|
||||
printLog("CoverageMap::printStats()...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_notAllInView=%d\n",_notAllInView);
|
||||
printLog("_maxPolygonsUsed=%d\n",CoverageRegion::_maxPolygonsUsed);
|
||||
printLog("_totalPolygons=%d\n",CoverageRegion::_totalPolygons);
|
||||
printLog("_occlusionTests=%d\n",CoverageRegion::_occlusionTests);
|
||||
printLog("_regionSkips=%d\n",CoverageRegion::_regionSkips);
|
||||
printLog("_tooSmallSkips=%d\n",CoverageRegion::_tooSmallSkips);
|
||||
printLog("_regionFullSkips=%d\n",CoverageRegion::_regionFullSkips);
|
||||
printLog("_outOfOrderPolygon=%d\n",CoverageRegion::_outOfOrderPolygon);
|
||||
printLog("_clippedPolygons=%d\n",CoverageRegion::_clippedPolygons);
|
||||
}
|
||||
|
||||
void CoverageMap::erase() {
|
||||
// tell our regions to erase()
|
||||
_topHalf.erase();
|
||||
|
@ -81,19 +100,19 @@ void CoverageMap::erase() {
|
|||
|
||||
if (_isRoot && wantDebugging) {
|
||||
printLog("CoverageMap last to be deleted...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_maxPolygonsUsed=%d\n",CoverageRegion::_maxPolygonsUsed);
|
||||
printLog("_totalPolygons=%d\n",CoverageRegion::_totalPolygons);
|
||||
printLog("_occlusionTests=%d\n",CoverageRegion::_occlusionTests);
|
||||
printLog("_outOfOrderPolygon=%d\n",CoverageRegion::_outOfOrderPolygon);
|
||||
printStats();
|
||||
|
||||
CoverageRegion::_maxPolygonsUsed = 0;
|
||||
CoverageRegion::_totalPolygons = 0;
|
||||
CoverageRegion::_occlusionTests = 0;
|
||||
CoverageRegion::_regionSkips = 0;
|
||||
CoverageRegion::_tooSmallSkips = 0;
|
||||
CoverageRegion::_regionFullSkips = 0;
|
||||
CoverageRegion::_outOfOrderPolygon = 0;
|
||||
CoverageRegion::_clippedPolygons = 0;
|
||||
_mapCount = 0;
|
||||
_checkMapRootCalls = 0;
|
||||
_notAllInView = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,16 +140,60 @@ BoundingBox CoverageMap::getChildBoundingBox(int childIndex) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int CoverageMap::getPolygonCount() const {
|
||||
return (_topHalf.getPolygonCount() +
|
||||
_bottomHalf.getPolygonCount() +
|
||||
_leftHalf.getPolygonCount() +
|
||||
_rightHalf.getPolygonCount() +
|
||||
_remainder.getPolygonCount());
|
||||
}
|
||||
|
||||
VoxelProjectedPolygon* CoverageMap::getPolygon(int index) const {
|
||||
int base = 0;
|
||||
if ((index - base) < _topHalf.getPolygonCount()) {
|
||||
return _topHalf.getPolygon((index - base));
|
||||
}
|
||||
base += _topHalf.getPolygonCount();
|
||||
|
||||
if ((index - base) < _bottomHalf.getPolygonCount()) {
|
||||
return _bottomHalf.getPolygon((index - base));
|
||||
}
|
||||
base += _bottomHalf.getPolygonCount();
|
||||
|
||||
if ((index - base) < _leftHalf.getPolygonCount()) {
|
||||
return _leftHalf.getPolygon((index - base));
|
||||
}
|
||||
base += _leftHalf.getPolygonCount();
|
||||
|
||||
if ((index - base) < _rightHalf.getPolygonCount()) {
|
||||
return _rightHalf.getPolygon((index - base));
|
||||
}
|
||||
base += _rightHalf.getPolygonCount();
|
||||
|
||||
if ((index - base) < _remainder.getPolygonCount()) {
|
||||
return _remainder.getPolygon((index - base));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
|
||||
CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, bool storeIt) {
|
||||
|
||||
if (_isRoot) {
|
||||
_checkMapRootCalls++;
|
||||
|
||||
//printLog("CoverageMap::checkMap()... storeIt=%s\n", debug::valueOf(storeIt));
|
||||
//polygon->printDebugDetails();
|
||||
|
||||
}
|
||||
|
||||
// short circuit: we don't handle polygons that aren't all in view, so, if the polygon in question is
|
||||
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
|
||||
if (!polygon->getAllInView()) {
|
||||
_notAllInView++;
|
||||
//printLog("CoverageMap2::checkMap()... V2_OCCLUDED\n");
|
||||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
|
@ -142,22 +205,25 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
bool fitsInAHalf = false;
|
||||
|
||||
// Check each half of the box independently
|
||||
if (_topHalf.contains(polygonBox)) {
|
||||
result = _topHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_topHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_bottomHalf.contains(polygonBox)) {
|
||||
result = _bottomHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_bottomHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_leftHalf.contains(polygonBox)) {
|
||||
result = _leftHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_leftHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_rightHalf.contains(polygonBox)) {
|
||||
result = _rightHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_rightHalf;
|
||||
fitsInAHalf = true;
|
||||
const bool useRegions = true; // for now we will continue to use regions
|
||||
if (useRegions) {
|
||||
if (_topHalf.contains(polygonBox)) {
|
||||
result = _topHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_topHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_bottomHalf.contains(polygonBox)) {
|
||||
result = _bottomHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_bottomHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_leftHalf.contains(polygonBox)) {
|
||||
result = _leftHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_leftHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_rightHalf.contains(polygonBox)) {
|
||||
result = _rightHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_rightHalf;
|
||||
fitsInAHalf = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got this far, there are one of two possibilities, either a polygon doesn't fit
|
||||
|
@ -171,36 +237,77 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
// It's possible that this first set of checks might have resulted in an out of order polygon
|
||||
// in which case we just return..
|
||||
if (result == STORED || result == OCCLUDED) {
|
||||
|
||||
/*
|
||||
if (result == STORED)
|
||||
printLog("CoverageMap2::checkMap()... STORED\n");
|
||||
else
|
||||
printLog("CoverageMap2::checkMap()... OCCLUDED\n");
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// if we made it here, then it means the polygon being stored is not occluded
|
||||
// at this level of the quad tree, so we can continue to insert it into the map.
|
||||
// First we check to see if it fits in any of our sub maps
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
BoundingBox childMapBoundingBox = getChildBoundingBox(i);
|
||||
if (childMapBoundingBox.contains(polygon->getBoundingBox())) {
|
||||
// if no child map exists yet, then create it
|
||||
if (!_childMaps[i]) {
|
||||
_childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons);
|
||||
const bool useChildMaps = true; // for now we will continue to use child maps
|
||||
if (useChildMaps) {
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
BoundingBox childMapBoundingBox = getChildBoundingBox(i);
|
||||
if (childMapBoundingBox.contains(polygon->getBoundingBox())) {
|
||||
// if no child map exists yet, then create it
|
||||
if (!_childMaps[i]) {
|
||||
_childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons);
|
||||
}
|
||||
result = _childMaps[i]->checkMap(polygon, storeIt);
|
||||
|
||||
/*
|
||||
switch (result) {
|
||||
case STORED:
|
||||
printLog("checkMap() = STORED\n");
|
||||
break;
|
||||
case NOT_STORED:
|
||||
printLog("checkMap() = NOT_STORED\n");
|
||||
break;
|
||||
case OCCLUDED:
|
||||
printLog("checkMap() = OCCLUDED\n");
|
||||
break;
|
||||
default:
|
||||
printLog("checkMap() = ????? \n");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
return _childMaps[i]->checkMap(polygon, storeIt);
|
||||
}
|
||||
}
|
||||
// if we got this far, then the polygon is in our bounding box, but doesn't fit in
|
||||
// any of our child bounding boxes, so we should add it here.
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
storeIn->storeInArray(polygon);
|
||||
return STORED;
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
if (storeIn->getPolygonCount() < MAX_POLYGONS_PER_REGION) {
|
||||
storeIn->storeInArray(polygon);
|
||||
//printLog("CoverageMap2::checkMap()... STORED\n");
|
||||
return STORED;
|
||||
} else {
|
||||
CoverageRegion::_regionFullSkips++;
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
CoverageRegion::_tooSmallSkips++;
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
}
|
||||
//printLog("CoverageMap2::checkMap()... DOESNT_FIT\n");
|
||||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
|
@ -223,12 +330,13 @@ void CoverageRegion::init() {
|
|||
_polygonArraySize = 0;
|
||||
_polygons = NULL;
|
||||
_polygonDistances = NULL;
|
||||
_polygonSizes = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CoverageRegion::erase() {
|
||||
|
||||
/*
|
||||
/**
|
||||
if (_polygonCount) {
|
||||
printLog("CoverageRegion::erase()...\n");
|
||||
printLog("_polygonCount=%d\n",_polygonCount);
|
||||
|
@ -238,7 +346,7 @@ void CoverageRegion::erase() {
|
|||
// _polygons[i]->getBoundingBox().printDebugDetails();
|
||||
//}
|
||||
}
|
||||
*/
|
||||
**/
|
||||
// If we're in charge of managing the polygons, then clean them up first
|
||||
if (_managePolygons) {
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
|
@ -258,11 +366,16 @@ void CoverageRegion::erase() {
|
|||
delete[] _polygonDistances;
|
||||
_polygonDistances = NULL;
|
||||
}
|
||||
if (_polygonSizes) {
|
||||
delete[] _polygonSizes;
|
||||
_polygonSizes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CoverageRegion::growPolygonArray() {
|
||||
VoxelProjectedPolygon** newPolygons = new VoxelProjectedPolygon*[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
float* newSizes = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
|
||||
|
||||
if (_polygons) {
|
||||
|
@ -270,9 +383,12 @@ void CoverageRegion::growPolygonArray() {
|
|||
delete[] _polygons;
|
||||
memcpy(newDistances, _polygonDistances, sizeof(float) * _polygonCount);
|
||||
delete[] _polygonDistances;
|
||||
memcpy(newSizes, _polygonSizes, sizeof(float) * _polygonCount);
|
||||
delete[] _polygonSizes;
|
||||
}
|
||||
_polygons = newPolygons;
|
||||
_polygons = newPolygons;
|
||||
_polygonDistances = newDistances;
|
||||
_polygonSizes = newSizes;
|
||||
_polygonArraySize = _polygonArraySize + DEFAULT_GROW_SIZE;
|
||||
//printLog("CoverageMap::growPolygonArray() _polygonArraySize=%d...\n",_polygonArraySize);
|
||||
}
|
||||
|
@ -297,26 +413,87 @@ const char* CoverageRegion::getRegionName() const {
|
|||
int CoverageRegion::_maxPolygonsUsed = 0;
|
||||
int CoverageRegion::_totalPolygons = 0;
|
||||
int CoverageRegion::_occlusionTests = 0;
|
||||
int CoverageRegion::_regionSkips = 0;
|
||||
int CoverageRegion::_tooSmallSkips = 0;
|
||||
int CoverageRegion::_regionFullSkips = 0;
|
||||
int CoverageRegion::_outOfOrderPolygon = 0;
|
||||
int CoverageRegion::_clippedPolygons = 0;
|
||||
|
||||
|
||||
bool CoverageRegion::mergeItemsInArray(VoxelProjectedPolygon* seed, bool seedInArray) {
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
VoxelProjectedPolygon* otherPolygon = _polygons[i];
|
||||
if (otherPolygon->canMerge(*seed)) {
|
||||
otherPolygon->merge(*seed);
|
||||
|
||||
if (seedInArray) {
|
||||
const int IGNORED = NULL;
|
||||
// remove this otherOtherPolygon for our polygon array
|
||||
_polygonCount = removeFromSortedArrays((void*)seed,
|
||||
(void**)_polygons, _polygonDistances, IGNORED,
|
||||
_polygonCount, _polygonArraySize);
|
||||
_totalPolygons--;
|
||||
}
|
||||
|
||||
//printLog("_polygonCount=%d\n",_polygonCount);
|
||||
|
||||
// clean up
|
||||
if (_managePolygons) {
|
||||
delete seed;
|
||||
}
|
||||
|
||||
// Now run again using our newly merged polygon as the seed
|
||||
mergeItemsInArray(otherPolygon, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// just handles storage in the array, doesn't test for occlusion or
|
||||
// determining if this is the correct map to store in!
|
||||
void CoverageRegion::storeInArray(VoxelProjectedPolygon* polygon) {
|
||||
|
||||
_currentCoveredBounds.explandToInclude(polygon->getBoundingBox());
|
||||
|
||||
|
||||
// Before we actually store this polygon in the array, check to see if this polygon can be merged to any of the existing
|
||||
// polygons already in our array.
|
||||
if (mergeItemsInArray(polygon, false)) {
|
||||
return; // exit early
|
||||
}
|
||||
|
||||
// only after we attempt to merge!
|
||||
_totalPolygons++;
|
||||
|
||||
if (_polygonArraySize < _polygonCount + 1) {
|
||||
growPolygonArray();
|
||||
}
|
||||
|
||||
// This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to
|
||||
// be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the
|
||||
// insertion point in this array, and shift the array accordingly
|
||||
// As an experiment we're going to see if we get an improvement by storing the polygons in coverage area sorted order
|
||||
// this means the bigger polygons are earlier in the array. We should have a higher probability of being occluded earlier
|
||||
// in the list. We still check to see if the polygon is "in front" of the target polygon before we test occlusion. Since
|
||||
// sometimes things come out of order.
|
||||
const bool SORT_BY_SIZE = false;
|
||||
const int IGNORED = NULL;
|
||||
_polygonCount = insertIntoSortedArrays((void*)polygon, polygon->getDistance(), IGNORED,
|
||||
(void**)_polygons, _polygonDistances, IGNORED,
|
||||
_polygonCount, _polygonArraySize);
|
||||
|
||||
if (SORT_BY_SIZE) {
|
||||
// This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to
|
||||
// be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the
|
||||
// insertion point in this array, and shift the array accordingly
|
||||
float area = polygon->getBoundingBox().area();
|
||||
float reverseArea = 4.0f - area;
|
||||
//printLog("store by size area=%f reverse area=%f\n", area, reverseArea);
|
||||
_polygonCount = insertIntoSortedArrays((void*)polygon, reverseArea, IGNORED,
|
||||
(void**)_polygons, _polygonSizes, IGNORED,
|
||||
_polygonCount, _polygonArraySize);
|
||||
} else {
|
||||
const int IGNORED = NULL;
|
||||
_polygonCount = insertIntoSortedArrays((void*)polygon, polygon->getDistance(), IGNORED,
|
||||
(void**)_polygons, _polygonDistances, IGNORED,
|
||||
_polygonCount, _polygonArraySize);
|
||||
}
|
||||
|
||||
// Debugging and Optimization Tuning code.
|
||||
if (_polygonCount > _maxPolygonsUsed) {
|
||||
_maxPolygonsUsed = _polygonCount;
|
||||
|
@ -335,37 +512,47 @@ CoverageMapStorageResult CoverageRegion::checkRegion(VoxelProjectedPolygon* poly
|
|||
|
||||
if (_isRoot || _myBoundingBox.contains(polygonBox)) {
|
||||
result = NOT_STORED; // if we got here, then we DO fit...
|
||||
|
||||
// only actually check the polygons if this polygon is in the covered bounds for this region
|
||||
if (!_currentCoveredBounds.contains(polygonBox)) {
|
||||
_regionSkips += _polygonCount;
|
||||
} else {
|
||||
// check to make sure this polygon isn't occluded by something at this level
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i];
|
||||
|
||||
// check to make sure this polygon isn't occluded by something at this level
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i];
|
||||
// Check to make sure that the polygon in question is "behind" the polygon in the list
|
||||
// otherwise, we don't need to test it's occlusion (although, it means we've potentially
|
||||
// added an item previously that may be occluded??? Is that possible? Maybe not, because two
|
||||
// voxels can't have the exact same outline. So one occludes the other, they can't both occlude
|
||||
// each other.
|
||||
|
||||
|
||||
_occlusionTests++;
|
||||
if (polygonAtThisLevel->occludes(*polygon)) {
|
||||
// if the polygonAtThisLevel is actually behind the one we're inserting, then we don't
|
||||
// want to report our inserted one as occluded, but we do want to add our inserted one.
|
||||
if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) {
|
||||
_outOfOrderPolygon++;
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
// Check to make sure that the polygon in question is "behind" the polygon in the list
|
||||
// otherwise, we don't need to test it's occlusion (although, it means we've potentially
|
||||
// added an item previously that may be occluded??? Is that possible? Maybe not, because two
|
||||
// voxels can't have the exact same outline. So one occludes the other, they can't both occlude
|
||||
// each other.
|
||||
|
||||
_occlusionTests++;
|
||||
if (polygonAtThisLevel->occludes(*polygon)) {
|
||||
// if the polygonAtThisLevel is actually behind the one we're inserting, then we don't
|
||||
// want to report our inserted one as occluded, but we do want to add our inserted one.
|
||||
if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) {
|
||||
_outOfOrderPolygon++;
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
if (getPolygonCount() < MAX_POLYGONS_PER_REGION) {
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
} else {
|
||||
CoverageRegion::_regionFullSkips++;
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
_tooSmallSkips++;
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
// this polygon is occluded by a closer polygon, so don't store it, and let the caller know
|
||||
return OCCLUDED;
|
||||
}
|
||||
// this polygon is occluded by a closer polygon, so don't store it, and let the caller know
|
||||
return OCCLUDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,24 +31,38 @@ public:
|
|||
static int _maxPolygonsUsed;
|
||||
static int _totalPolygons;
|
||||
static int _occlusionTests;
|
||||
static int _regionSkips;
|
||||
static int _tooSmallSkips;
|
||||
static int _regionFullSkips;
|
||||
static int _outOfOrderPolygon;
|
||||
static int _clippedPolygons;
|
||||
|
||||
|
||||
const char* getRegionName() const;
|
||||
|
||||
int getPolygonCount() const { return _polygonCount; };
|
||||
VoxelProjectedPolygon* getPolygon(int index) const { return _polygons[index]; };
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
bool _isRoot; // is this map the root, if so, it never returns DOESNT_FIT
|
||||
BoundingBox _myBoundingBox;
|
||||
BoundingBox _currentCoveredBounds; // area in this region currently covered by some polygon
|
||||
bool _managePolygons; // will the coverage map delete the polygons on destruct
|
||||
RegionName _regionName;
|
||||
int _polygonCount; // how many polygons at this level
|
||||
int _polygonArraySize; // how much room is there to store polygons at this level
|
||||
VoxelProjectedPolygon** _polygons;
|
||||
|
||||
// we will use one or the other of these depending on settings in the code.
|
||||
float* _polygonDistances;
|
||||
float* _polygonSizes;
|
||||
void growPolygonArray();
|
||||
static const int DEFAULT_GROW_SIZE = 100;
|
||||
|
||||
bool mergeItemsInArray(VoxelProjectedPolygon* seed, bool seedInArray);
|
||||
|
||||
};
|
||||
|
||||
class CoverageMap {
|
||||
|
@ -68,9 +82,14 @@ public:
|
|||
BoundingBox getChildBoundingBox(int childIndex);
|
||||
|
||||
void erase(); // erase the coverage map
|
||||
void printStats();
|
||||
|
||||
static bool wantDebugging;
|
||||
|
||||
int getPolygonCount() const;
|
||||
VoxelProjectedPolygon* getPolygon(int index) const;
|
||||
CoverageMap* getChild(int childIndex) const { return _childMaps[childIndex]; };
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
|
@ -89,6 +108,7 @@ private:
|
|||
|
||||
static int _mapCount;
|
||||
static int _checkMapRootCalls;
|
||||
static int _notAllInView;
|
||||
};
|
||||
|
||||
|
||||
|
|
246
libraries/voxels/src/CoverageMapV2.cpp
Normal file
246
libraries/voxels/src/CoverageMapV2.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
//
|
||||
// CoverageMapV2.cpp -
|
||||
// hifi
|
||||
//
|
||||
// Added by Brad Hefta-Gaub on 06/11/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "CoverageMapV2.h"
|
||||
#include <SharedUtil.h>
|
||||
#include <cstring>
|
||||
#include "Log.h"
|
||||
|
||||
int CoverageMapV2::_mapCount = 0;
|
||||
int CoverageMapV2::_checkMapRootCalls = 0;
|
||||
int CoverageMapV2::_notAllInView = 0;
|
||||
bool CoverageMapV2::wantDebugging = false;
|
||||
|
||||
const BoundingBox CoverageMapV2::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f));
|
||||
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
//
|
||||
// (0,0) (windowWidth, 0)
|
||||
// -1,1 1,1
|
||||
// +-----------------------+
|
||||
// | | |
|
||||
// | | |
|
||||
// | -1,0 | |
|
||||
// |-----------+-----------|
|
||||
// | 0,0 |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// +-----------------------+
|
||||
// -1,-1 1,-1
|
||||
// (0,windowHeight) (windowWidth,windowHeight)
|
||||
//
|
||||
|
||||
// Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide
|
||||
// then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically
|
||||
// about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough"
|
||||
// then we can calculate a reasonable polygon area
|
||||
const int TYPICAL_SCREEN_WIDTH_IN_PIXELS = 1500;
|
||||
const int MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS = 10;
|
||||
const float TYPICAL_SCREEN_PIXEL_WIDTH = (2.0f / TYPICAL_SCREEN_WIDTH_IN_PIXELS);
|
||||
const float CoverageMapV2::MINIMUM_POLYGON_AREA_TO_STORE = (TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS) *
|
||||
(TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS);
|
||||
const float CoverageMapV2::NOT_COVERED = FLT_MAX;
|
||||
const float CoverageMapV2::MINIMUM_OCCLUSION_CHECK_AREA = MINIMUM_POLYGON_AREA_TO_STORE/10.0f; // one quarter the size of poly
|
||||
|
||||
|
||||
CoverageMapV2::CoverageMapV2(BoundingBox boundingBox, bool isRoot, bool isCovered, float coverageDistance) :
|
||||
_isRoot(isRoot),
|
||||
_myBoundingBox(boundingBox),
|
||||
_isCovered(isCovered),
|
||||
_coveredDistance(coverageDistance)
|
||||
{
|
||||
_mapCount++;
|
||||
init();
|
||||
//printLog("CoverageMapV2 created... _mapCount=%d\n",_mapCount);
|
||||
};
|
||||
|
||||
CoverageMapV2::~CoverageMapV2() {
|
||||
erase();
|
||||
};
|
||||
|
||||
void CoverageMapV2::erase() {
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
if (_childMaps[i]) {
|
||||
delete _childMaps[i];
|
||||
_childMaps[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_isRoot && wantDebugging) {
|
||||
printLog("CoverageMapV2 last to be deleted...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_notAllInView=%d\n",_notAllInView);
|
||||
_mapCount = 0;
|
||||
_checkMapRootCalls = 0;
|
||||
_notAllInView = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CoverageMapV2::init() {
|
||||
memset(_childMaps,0,sizeof(_childMaps));
|
||||
}
|
||||
|
||||
// 0 = bottom, left
|
||||
// 1 = bottom, right
|
||||
// 2 = top, left
|
||||
// 3 = top, right
|
||||
BoundingBox CoverageMapV2::getChildBoundingBox(int childIndex) {
|
||||
const int RIGHT_BIT = 1;
|
||||
const int TOP_BIT = 2;
|
||||
// initialize to our corner, and half our size
|
||||
BoundingBox result(_myBoundingBox.corner,_myBoundingBox.size/2.0f);
|
||||
// if our "right" bit is set, then add size.x to the corner
|
||||
if ((childIndex & RIGHT_BIT) == RIGHT_BIT) {
|
||||
result.corner.x += result.size.x;
|
||||
}
|
||||
// if our "top" bit is set, then add size.y to the corner
|
||||
if ((childIndex & TOP_BIT) == TOP_BIT) {
|
||||
result.corner.y += result.size.y;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
|
||||
CoverageMapV2StorageResult CoverageMapV2::checkMap(const VoxelProjectedPolygon* polygon, bool storeIt) {
|
||||
assert(_isRoot); // you can only call this on the root map!!!
|
||||
_checkMapRootCalls++;
|
||||
|
||||
// short circuit: if we're the root node (only case we're here), and we're covered, and this polygon is deeper than our
|
||||
// covered depth, then this polygon is occluded!
|
||||
if (_isCovered && _coveredDistance < polygon->getDistance()) {
|
||||
return V2_OCCLUDED;
|
||||
}
|
||||
|
||||
// short circuit: we don't handle polygons that aren't all in view, so, if the polygon in question is
|
||||
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
|
||||
if (!polygon->getAllInView()) {
|
||||
_notAllInView++;
|
||||
return V2_DOESNT_FIT;
|
||||
}
|
||||
|
||||
// Here's where we recursively check the polygon against the coverage map. We need to maintain two pieces of state.
|
||||
// The first state is: have we seen at least one "fully occluded" map items. If we haven't then we don't track the covered
|
||||
// state of the polygon.
|
||||
// The second piece of state is: Are all of our "fully occluded" map items "covered". If even one of these occluded map
|
||||
// items is not covered, then our polygon is not covered.
|
||||
bool seenOccludedMapNodes = false;
|
||||
bool allOccludedMapNodesCovered = false;
|
||||
|
||||
recurseMap(polygon, storeIt, seenOccludedMapNodes, allOccludedMapNodesCovered);
|
||||
|
||||
// Ok, no matter how we were called, if all our occluded map nodes are covered, then we know this polygon
|
||||
// is occluded, otherwise, we will report back to the caller about whether or not we stored the polygon
|
||||
if (allOccludedMapNodesCovered) {
|
||||
return V2_OCCLUDED;
|
||||
}
|
||||
if (storeIt) {
|
||||
return V2_STORED; // otherwise report that we STORED it
|
||||
}
|
||||
return V2_NOT_STORED; // unless we weren't asked to store it, then we didn't
|
||||
}
|
||||
|
||||
void CoverageMapV2::recurseMap(const VoxelProjectedPolygon* polygon, bool storeIt,
|
||||
bool& seenOccludedMapNodes, bool& allOccludedMapNodesCovered) {
|
||||
|
||||
// if we are really small, then we act like we don't intersect, this allows us to stop
|
||||
// recusing as we get to the smalles edge of the polygon
|
||||
if (_myBoundingBox.area() < MINIMUM_OCCLUSION_CHECK_AREA) {
|
||||
return; // stop recursion, we're done!
|
||||
}
|
||||
|
||||
// Determine if this map node intersects the polygon and/or is fully covered by the polygon
|
||||
// There are a couple special cases: If we're the root, we are assumed to intersect with all
|
||||
// polygons. Also, any map node that is fully occluded also intersects.
|
||||
bool nodeIsCoveredByPolygon = polygon->occludes(_myBoundingBox);
|
||||
bool nodeIsIntersectedByPolygon = nodeIsCoveredByPolygon || _isRoot || polygon->intersects(_myBoundingBox);
|
||||
|
||||
// If we don't intersect, then we can just return, we're done recursing
|
||||
if (!nodeIsIntersectedByPolygon) {
|
||||
return; // stop recursion, we're done!
|
||||
}
|
||||
|
||||
// At this point, we know our node intersects with the polygon. If this node is covered, then we want to treat it
|
||||
// as if the node was fully covered, because this allows us to short circuit further recursion...
|
||||
if (_isCovered && _coveredDistance < polygon->getDistance()) {
|
||||
nodeIsCoveredByPolygon = true; // fake it till you make it
|
||||
}
|
||||
|
||||
// If this node in the map is fully covered by our polygon, then we don't need to recurse any further, but
|
||||
// we do need to do some bookkeeping.
|
||||
if (nodeIsCoveredByPolygon) {
|
||||
// If this is the very first fully covered node we've seen, then we're initialize our allOccludedMapNodesCovered
|
||||
// to be our current covered state. This has the following effect: if this node isn't already covered, then by
|
||||
// definition, we know that at least one node for this polygon isn't covered, and therefore we aren't fully covered.
|
||||
if (!seenOccludedMapNodes) {
|
||||
allOccludedMapNodesCovered = (_isCovered && _coveredDistance < polygon->getDistance());
|
||||
// We need to mark that we've seen at least one node of our polygon! ;)
|
||||
seenOccludedMapNodes = true;
|
||||
} else {
|
||||
// If this is our second or later node of our polygon, then we need to track our allOccludedMapNodesCovered state
|
||||
allOccludedMapNodesCovered = allOccludedMapNodesCovered &&
|
||||
(_isCovered && _coveredDistance < polygon->getDistance());
|
||||
}
|
||||
|
||||
// if we're in store mode then we want to record that this node is covered.
|
||||
if (storeIt) {
|
||||
_isCovered = true;
|
||||
// store the minimum distance of our previous known distance, or our current polygon's distance. This is because
|
||||
// we know that we're at least covered at this distance, but if we had previously identified that we're covered
|
||||
// at a shallower distance, then we want to maintain that distance
|
||||
_coveredDistance = std::min(polygon->getDistance(), _coveredDistance);
|
||||
|
||||
// Note: this might be a good chance to delete child maps, but we're not going to do that at this point because
|
||||
// we're trying to maintain the known distances in the lower portion of the tree.
|
||||
}
|
||||
|
||||
// and since this node of the quad map is covered, we can safely stop recursion. because we know all smaller map
|
||||
// nodes will also be covered.
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got here, then it means we know that this node is not fully covered by the polygon, but it does intersect
|
||||
// with the polygon.
|
||||
|
||||
// Another case is that we aren't yet marked as covered, and so we should recurse and process smaller quad tree nodes.
|
||||
// Note: we use this to determine if we can collapse the child quad trees and mark this node as covered
|
||||
bool allChildrenOccluded = true;
|
||||
float maxChildCoveredDepth = NOT_COVERED;
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
BoundingBox childMapBoundingBox = getChildBoundingBox(i);
|
||||
// if no child map exists yet, then create it
|
||||
if (!_childMaps[i]) {
|
||||
// children get created with the coverage state of their parent.
|
||||
_childMaps[i] = new CoverageMapV2(childMapBoundingBox, NOT_ROOT, _isCovered, _coveredDistance);
|
||||
}
|
||||
|
||||
_childMaps[i]->recurseMap(polygon, storeIt, seenOccludedMapNodes, allOccludedMapNodesCovered);
|
||||
|
||||
// if so far, all of our children are covered, then record our furthest coverage distance
|
||||
if (allChildrenOccluded && _childMaps[i]->_isCovered) {
|
||||
maxChildCoveredDepth = std::max(maxChildCoveredDepth, _childMaps[i]->_coveredDistance);
|
||||
} else {
|
||||
// otherwise, at least one of our children is not covered, so not all are covered
|
||||
allChildrenOccluded = false;
|
||||
}
|
||||
}
|
||||
// if all the children are covered, this makes our quad tree "shallower" because it records that
|
||||
// entire quad is covered, it uses the "furthest" z-order so that if a shalower polygon comes through
|
||||
// we won't assume its occluded
|
||||
if (allChildrenOccluded && storeIt) {
|
||||
_isCovered = true;
|
||||
_coveredDistance = maxChildCoveredDepth;
|
||||
}
|
||||
|
||||
// normal exit case... return...
|
||||
}
|
69
libraries/voxels/src/CoverageMapV2.h
Normal file
69
libraries/voxels/src/CoverageMapV2.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// CoverageMapV2.h - 2D CoverageMapV2 Quad tree for storage of VoxelProjectedPolygons
|
||||
// hifi
|
||||
//
|
||||
// Added by Brad Hefta-Gaub on 06/11/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef _COVERAGE_MAP_V2_
|
||||
#define _COVERAGE_MAP_V2_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
typedef enum {
|
||||
V2_DOESNT_FIT, V2_STORED, V2_NOT_STORED,
|
||||
V2_INTERSECT, V2_NO_INTERSECT,
|
||||
V2_OCCLUDED, V2_NOT_OCCLUDED
|
||||
} CoverageMapV2StorageResult;
|
||||
|
||||
class CoverageMapV2 {
|
||||
|
||||
public:
|
||||
static const int NUMBER_OF_CHILDREN = 4;
|
||||
static const bool NOT_ROOT = false;
|
||||
static const bool IS_ROOT = true;
|
||||
static const BoundingBox ROOT_BOUNDING_BOX;
|
||||
static const float MINIMUM_POLYGON_AREA_TO_STORE;
|
||||
static const float NOT_COVERED;
|
||||
static const float MINIMUM_OCCLUSION_CHECK_AREA;
|
||||
static bool wantDebugging;
|
||||
|
||||
CoverageMapV2(BoundingBox boundingBox = ROOT_BOUNDING_BOX, bool isRoot = IS_ROOT,
|
||||
bool isCovered = false, float coverageDistance = NOT_COVERED);
|
||||
~CoverageMapV2();
|
||||
|
||||
CoverageMapV2StorageResult checkMap(const VoxelProjectedPolygon* polygon, bool storeIt = true);
|
||||
|
||||
BoundingBox getChildBoundingBox(int childIndex);
|
||||
const BoundingBox& getBoundingBox() const { return _myBoundingBox; };
|
||||
CoverageMapV2* getChild(int childIndex) const { return _childMaps[childIndex]; };
|
||||
bool isCovered() const { return _isCovered; };
|
||||
|
||||
void erase(); // erase the coverage map
|
||||
|
||||
void render();
|
||||
|
||||
|
||||
private:
|
||||
void recurseMap(const VoxelProjectedPolygon* polygon, bool storeIt,
|
||||
bool& seenOccludedMapNodes, bool& allOccludedMapNodesCovered);
|
||||
|
||||
void init();
|
||||
|
||||
bool _isRoot;
|
||||
BoundingBox _myBoundingBox;
|
||||
CoverageMapV2* _childMaps[NUMBER_OF_CHILDREN];
|
||||
|
||||
bool _isCovered;
|
||||
float _coveredDistance;
|
||||
|
||||
static int _mapCount;
|
||||
static int _checkMapRootCalls;
|
||||
static int _notAllInView;
|
||||
};
|
||||
|
||||
|
||||
#endif // _COVERAGE_MAP_V2_
|
|
@ -5,6 +5,9 @@
|
|||
// Created by Andrzej Kapolka on 5/21/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <Log.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
|
@ -117,6 +120,7 @@ glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3&
|
|||
}
|
||||
|
||||
// Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect?
|
||||
// from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html
|
||||
bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) {
|
||||
int d1 = computeDirection(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p1.x, r1p1.y);
|
||||
int d2 = computeDirection(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p2.x, r1p2.y);
|
||||
|
@ -140,3 +144,193 @@ int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk)
|
|||
float b = (xj - xi) * (yk - yi);
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Polygon Clipping routines inspired by, pseudo code found here: http://www.cs.rit.edu/~icss571/clipTrans/PolyClipBack.html
|
||||
//
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
//
|
||||
// (0,0) (windowWidth, 0)
|
||||
// -1,1 1,1
|
||||
// +-----------------------+
|
||||
// | | |
|
||||
// | | |
|
||||
// | -1,0 | |
|
||||
// |-----------+-----------|
|
||||
// | 0,0 |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// +-----------------------+
|
||||
// -1,-1 1,-1
|
||||
// (0,windowHeight) (windowWidth,windowHeight)
|
||||
//
|
||||
|
||||
const float PolygonClip::TOP_OF_CLIPPING_WINDOW = 1.0f;
|
||||
const float PolygonClip::BOTTOM_OF_CLIPPING_WINDOW = -1.0f;
|
||||
const float PolygonClip::LEFT_OF_CLIPPING_WINDOW = -1.0f;
|
||||
const float PolygonClip::RIGHT_OF_CLIPPING_WINDOW = 1.0f;
|
||||
|
||||
const glm::vec2 PolygonClip::TOP_LEFT_CLIPPING_WINDOW ( LEFT_OF_CLIPPING_WINDOW , TOP_OF_CLIPPING_WINDOW );
|
||||
const glm::vec2 PolygonClip::TOP_RIGHT_CLIPPING_WINDOW ( RIGHT_OF_CLIPPING_WINDOW, TOP_OF_CLIPPING_WINDOW );
|
||||
const glm::vec2 PolygonClip::BOTTOM_LEFT_CLIPPING_WINDOW ( LEFT_OF_CLIPPING_WINDOW , BOTTOM_OF_CLIPPING_WINDOW );
|
||||
const glm::vec2 PolygonClip::BOTTOM_RIGHT_CLIPPING_WINDOW ( RIGHT_OF_CLIPPING_WINDOW, BOTTOM_OF_CLIPPING_WINDOW );
|
||||
|
||||
void PolygonClip::clipToScreen(const glm::vec2* inputVertexArray, int inLength, glm::vec2*& outputVertexArray, int& outLength) {
|
||||
int tempLengthA = inLength;
|
||||
int tempLengthB;
|
||||
int maxLength = inLength * 2;
|
||||
glm::vec2* tempVertexArrayA = new glm::vec2[maxLength];
|
||||
glm::vec2* tempVertexArrayB = new glm::vec2[maxLength];
|
||||
|
||||
// set up our temporary arrays
|
||||
memcpy(tempVertexArrayA, inputVertexArray, sizeof(glm::vec2) * inLength);
|
||||
|
||||
// Left edge
|
||||
LineSegment2 edge;
|
||||
edge[0] = TOP_LEFT_CLIPPING_WINDOW;
|
||||
edge[1] = BOTTOM_LEFT_CLIPPING_WINDOW;
|
||||
// clip the array from tempVertexArrayA and copy end result to tempVertexArrayB
|
||||
sutherlandHodgmanPolygonClip(tempVertexArrayA, tempVertexArrayB, tempLengthA, tempLengthB, edge);
|
||||
// clean the array from tempVertexArrayA and copy cleaned result to tempVertexArrayA
|
||||
copyCleanArray(tempLengthA, tempVertexArrayA, tempLengthB, tempVertexArrayB);
|
||||
|
||||
// Bottom Edge
|
||||
edge[0] = BOTTOM_LEFT_CLIPPING_WINDOW;
|
||||
edge[1] = BOTTOM_RIGHT_CLIPPING_WINDOW;
|
||||
// clip the array from tempVertexArrayA and copy end result to tempVertexArrayB
|
||||
sutherlandHodgmanPolygonClip(tempVertexArrayA, tempVertexArrayB, tempLengthA, tempLengthB, edge);
|
||||
// clean the array from tempVertexArrayA and copy cleaned result to tempVertexArrayA
|
||||
copyCleanArray(tempLengthA, tempVertexArrayA, tempLengthB, tempVertexArrayB);
|
||||
|
||||
// Right Edge
|
||||
edge[0] = BOTTOM_RIGHT_CLIPPING_WINDOW;
|
||||
edge[1] = TOP_RIGHT_CLIPPING_WINDOW;
|
||||
// clip the array from tempVertexArrayA and copy end result to tempVertexArrayB
|
||||
sutherlandHodgmanPolygonClip(tempVertexArrayA, tempVertexArrayB, tempLengthA, tempLengthB, edge);
|
||||
// clean the array from tempVertexArrayA and copy cleaned result to tempVertexArrayA
|
||||
copyCleanArray(tempLengthA, tempVertexArrayA, tempLengthB, tempVertexArrayB);
|
||||
|
||||
// Top Edge
|
||||
edge[0] = TOP_RIGHT_CLIPPING_WINDOW;
|
||||
edge[1] = TOP_LEFT_CLIPPING_WINDOW;
|
||||
// clip the array from tempVertexArrayA and copy end result to tempVertexArrayB
|
||||
sutherlandHodgmanPolygonClip(tempVertexArrayA, tempVertexArrayB, tempLengthA, tempLengthB, edge);
|
||||
// clean the array from tempVertexArrayA and copy cleaned result to tempVertexArrayA
|
||||
copyCleanArray(tempLengthA, tempVertexArrayA, tempLengthB, tempVertexArrayB);
|
||||
|
||||
// copy final output to outputVertexArray
|
||||
outputVertexArray = tempVertexArrayA;
|
||||
outLength = tempLengthA;
|
||||
|
||||
// cleanup our unused temporary buffer...
|
||||
delete[] tempVertexArrayB;
|
||||
|
||||
// Note: we don't delete tempVertexArrayA, because that's the caller's responsibility
|
||||
}
|
||||
|
||||
void PolygonClip::sutherlandHodgmanPolygonClip(glm::vec2* inVertexArray, glm::vec2* outVertexArray,
|
||||
int inLength, int& outLength, const LineSegment2& clipBoundary) {
|
||||
glm::vec2 start, end; // Start, end point of current polygon edge
|
||||
glm::vec2 intersection; // Intersection point with a clip boundary
|
||||
|
||||
outLength = 0;
|
||||
start = inVertexArray[inLength - 1]; // Start with the last vertex in inVertexArray
|
||||
for (int j = 0; j < inLength; j++) {
|
||||
end = inVertexArray[j]; // Now start and end correspond to the vertices
|
||||
|
||||
// Cases 1 and 4 - the endpoint is inside the boundary
|
||||
if (pointInsideBoundary(end,clipBoundary)) {
|
||||
// Case 1 - Both inside
|
||||
if (pointInsideBoundary(start, clipBoundary)) {
|
||||
appendPoint(end, outLength, outVertexArray);
|
||||
} else { // Case 4 - end is inside, but start is outside
|
||||
segmentIntersectsBoundary(start, end, clipBoundary, intersection);
|
||||
appendPoint(intersection, outLength, outVertexArray);
|
||||
appendPoint(end, outLength, outVertexArray);
|
||||
}
|
||||
} else { // Cases 2 and 3 - end is outside
|
||||
if (pointInsideBoundary(start, clipBoundary)) {
|
||||
// Cases 2 - start is inside, end is outside
|
||||
segmentIntersectsBoundary(start, end, clipBoundary, intersection);
|
||||
appendPoint(intersection, outLength, outVertexArray);
|
||||
} else {
|
||||
// Case 3 - both are outside, No action
|
||||
}
|
||||
}
|
||||
start = end; // Advance to next pair of vertices
|
||||
}
|
||||
}
|
||||
|
||||
bool PolygonClip::pointInsideBoundary(const glm::vec2& testVertex, const LineSegment2& clipBoundary) {
|
||||
// bottom edge
|
||||
if (clipBoundary[1].x > clipBoundary[0].x) {
|
||||
if (testVertex.y >= clipBoundary[0].y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// top edge
|
||||
if (clipBoundary[1].x < clipBoundary[0].x) {
|
||||
if (testVertex.y <= clipBoundary[0].y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// right edge
|
||||
if (clipBoundary[1].y > clipBoundary[0].y) {
|
||||
if (testVertex.x <= clipBoundary[1].x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// left edge
|
||||
if (clipBoundary[1].y < clipBoundary[0].y) {
|
||||
if (testVertex.x >= clipBoundary[1].x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PolygonClip::segmentIntersectsBoundary(const glm::vec2& first, const glm::vec2& second,
|
||||
const LineSegment2& clipBoundary, glm::vec2& intersection) {
|
||||
// horizontal
|
||||
if (clipBoundary[0].y==clipBoundary[1].y) {
|
||||
intersection.y = clipBoundary[0].y;
|
||||
intersection.x = first.x + (clipBoundary[0].y - first.y) * (second.x - first.x) / (second.y - first.y);
|
||||
} else { // Vertical
|
||||
intersection.x = clipBoundary[0].x;
|
||||
intersection.y = first.y + (clipBoundary[0].x - first.x) * (second.y - first.y) / (second.x - first.x);
|
||||
}
|
||||
}
|
||||
|
||||
void PolygonClip::appendPoint(glm::vec2 newVertex, int& outLength, glm::vec2* outVertexArray) {
|
||||
outVertexArray[outLength].x = newVertex.x;
|
||||
outVertexArray[outLength].y = newVertex.y;
|
||||
outLength++;
|
||||
}
|
||||
|
||||
// The copyCleanArray() function sets the resulting polygon of the previous step up to be the input polygon for next step of the
|
||||
// clipping algorithm. As the Sutherland-Hodgman algorithm is a polygon clipping algorithm, it does not handle line
|
||||
// clipping very well. The modification so that lines may be clipped as well as polygons is included in this function.
|
||||
// when completed vertexArrayA will be ready for output and/or next step of clipping
|
||||
void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& lengthB, glm::vec2* vertexArrayB) {
|
||||
// Fix lines: they will come back with a length of 3, from an original of length of 2
|
||||
if ((lengthA == 2) && (lengthB == 3)) {
|
||||
// The first vertex should be copied as is.
|
||||
vertexArrayA[0] = vertexArrayB[0];
|
||||
// If the first two vertices of the "B" array are same, then collapse them down to be the 2nd vertex
|
||||
if (vertexArrayB[0].x == vertexArrayB[1].x) {
|
||||
vertexArrayA[1] = vertexArrayB[2];
|
||||
} else {
|
||||
// Otherwise the first vertex should be the same as third vertex
|
||||
vertexArrayA[1] = vertexArrayB[1];
|
||||
}
|
||||
lengthA=2;
|
||||
} else {
|
||||
// for all other polygons, then just copy the vertexArrayB to vertextArrayA for next step
|
||||
lengthA = lengthB;
|
||||
for (int i = 0; i < lengthB; i++) {
|
||||
vertexArrayA[i] = vertexArrayB[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,39 @@ bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm
|
|||
bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk);
|
||||
int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk);
|
||||
|
||||
|
||||
typedef glm::vec2 LineSegment2[2];
|
||||
|
||||
// Polygon Clipping routines inspired by, pseudo code found here: http://www.cs.rit.edu/~icss571/clipTrans/PolyClipBack.html
|
||||
class PolygonClip {
|
||||
|
||||
public:
|
||||
static void clipToScreen(const glm::vec2* inputVertexArray, int length, glm::vec2*& outputVertexArray, int& outLength);
|
||||
|
||||
static const float TOP_OF_CLIPPING_WINDOW;
|
||||
static const float BOTTOM_OF_CLIPPING_WINDOW;
|
||||
static const float LEFT_OF_CLIPPING_WINDOW;
|
||||
static const float RIGHT_OF_CLIPPING_WINDOW;
|
||||
|
||||
static const glm::vec2 TOP_LEFT_CLIPPING_WINDOW;
|
||||
static const glm::vec2 TOP_RIGHT_CLIPPING_WINDOW;
|
||||
static const glm::vec2 BOTTOM_LEFT_CLIPPING_WINDOW;
|
||||
static const glm::vec2 BOTTOM_RIGHT_CLIPPING_WINDOW;
|
||||
|
||||
private:
|
||||
|
||||
static void sutherlandHodgmanPolygonClip(glm::vec2* inVertexArray, glm::vec2* outVertexArray,
|
||||
int inLength, int& outLength, const LineSegment2& clipBoundary);
|
||||
|
||||
static bool pointInsideBoundary(const glm::vec2& testVertex, const LineSegment2& clipBoundary);
|
||||
|
||||
static void segmentIntersectsBoundary(const glm::vec2& first, const glm::vec2& second,
|
||||
const LineSegment2& clipBoundary, glm::vec2& intersection);
|
||||
|
||||
static void appendPoint(glm::vec2 newVertex, int& outLength, glm::vec2* outVertexArray);
|
||||
|
||||
static void copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& lengthB, glm::vec2* vertexArrayB);
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__interface__GeometryUtil__) */
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 5/7/2013.
|
||||
//
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "SceneUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include <glm/gtc/noise.hpp>
|
||||
|
||||
#include "SceneUtils.h"
|
||||
|
||||
void addCornersAndAxisLines(VoxelTree* tree) {
|
||||
// We want our corner voxels to be about 1/2 meter high, and our TREE_SCALE is in meters, so...
|
||||
float voxelSize = 0.5f / TREE_SCALE;
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Tomáš Horáček on 6/25/13.
|
||||
//
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "SquarePixelMap.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SquarePixelMap.h"
|
||||
|
||||
#define CHILD_COORD_X_IS_1 0x1
|
||||
#define CHILD_COORD_Y_IS_1 0x2
|
||||
|
|
245
libraries/voxels/src/Tags.cpp
Normal file
245
libraries/voxels/src/Tags.cpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
//
|
||||
// Tags.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clement Brisset on 7/3/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Tags.h"
|
||||
#include <Log.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <zconf.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Tag::Tag(int tagId, std::stringstream &ss) : _tagId(tagId) {
|
||||
int size = ss.get() << 8 | ss.get();
|
||||
|
||||
_name.clear();
|
||||
for (int i = 0; i < size; ++i) { _name += ss.get();
|
||||
}
|
||||
}
|
||||
|
||||
Tag* Tag::readTag(int tagId, std::stringstream &ss) {
|
||||
|
||||
switch (tagId) {
|
||||
case TAG_Byte:
|
||||
return new TagByte(ss);
|
||||
case TAG_Short:
|
||||
return new TagShort(ss);
|
||||
case TAG_Int:
|
||||
return new TagInt(ss);
|
||||
case TAG_Long:
|
||||
return new TagLong(ss);
|
||||
case TAG_Float:
|
||||
return new TagFloat(ss);
|
||||
case TAG_Double:
|
||||
return new TagDouble(ss);
|
||||
case TAG_Byte_Array:
|
||||
return new TagByteArray(ss);
|
||||
case TAG_String:
|
||||
return new TagString(ss);
|
||||
case TAG_List:
|
||||
return new TagList(ss);
|
||||
case TAG_Compound:
|
||||
return new TagCompound(ss);
|
||||
case TAG_Int_Array:
|
||||
return new TagIntArray(ss);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TagByte::TagByte(std::stringstream &ss) : Tag(TAG_Byte, ss) {
|
||||
_data = ss.get();
|
||||
}
|
||||
|
||||
TagShort::TagShort(std::stringstream &ss) : Tag(TAG_Short, ss) {
|
||||
_data = ss.get() << 8 | ss.get();
|
||||
}
|
||||
|
||||
TagInt::TagInt(std::stringstream &ss) : Tag(TAG_Int, ss) {
|
||||
_data = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
|
||||
}
|
||||
|
||||
TagLong::TagLong(std::stringstream &ss) : Tag(TAG_Long, ss) {
|
||||
_data = (((int64_t) ss.get()) << 56 | ((int64_t) ss.get()) << 48
|
||||
|((int64_t) ss.get()) << 40 | ((int64_t) ss.get()) << 32
|
||||
| ss.get() << 24 | ss.get() << 16
|
||||
| ss.get() << 8 | ss.get());
|
||||
}
|
||||
|
||||
// We don't need Float and double, so we just ignore the bytes
|
||||
TagFloat::TagFloat(std::stringstream &ss) : Tag(TAG_Float, ss) {
|
||||
ss.seekg(4, ss.cur);
|
||||
}
|
||||
|
||||
TagDouble::TagDouble(std::stringstream &ss) : Tag(TAG_Double, ss) {
|
||||
ss.seekg(8, ss.cur);
|
||||
}
|
||||
|
||||
TagByteArray::TagByteArray(std::stringstream &ss) : Tag(TAG_Byte_Array, ss) {
|
||||
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
|
||||
|
||||
_data = new char[_size];
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
_data[i] = ss.get();
|
||||
}
|
||||
}
|
||||
|
||||
TagString::TagString(std::stringstream &ss) : Tag(TAG_String, ss) {
|
||||
_size = ss.get() << 8 | ss.get();
|
||||
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
_data += ss.get();
|
||||
}
|
||||
}
|
||||
|
||||
TagList::TagList(std::stringstream &ss) :
|
||||
Tag(TAG_List, ss) {
|
||||
_tagId = ss.get();
|
||||
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
|
||||
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
ss.putback(0);
|
||||
ss.putback(0);
|
||||
_data.push_back(readTag(_tagId, ss));
|
||||
}
|
||||
}
|
||||
|
||||
TagCompound::TagCompound(std::stringstream &ss) :
|
||||
Tag(TAG_Compound, ss),
|
||||
_size(0),
|
||||
_width(0),
|
||||
_length(0),
|
||||
_height(0),
|
||||
_blocksData(NULL),
|
||||
_blocksId(NULL)
|
||||
{
|
||||
int tagId;
|
||||
|
||||
while (TAG_End != (tagId = ss.get())) {
|
||||
_data.push_back(readTag(tagId, ss));
|
||||
++_size;
|
||||
|
||||
if (NULL == _data.back()) {
|
||||
_blocksId = NULL;
|
||||
_blocksData = NULL;
|
||||
return;
|
||||
} else if (TAG_Short == tagId) {
|
||||
if ("Width" == _data.back()->getName()) {
|
||||
_width = ((TagShort*) _data.back())->getData();
|
||||
} else if ("Height" == _data.back()->getName()) {
|
||||
_height = ((TagShort*) _data.back())->getData();
|
||||
} else if ("Length" == _data.back()->getName()) {
|
||||
_length = ((TagShort*) _data.back())->getData();
|
||||
}
|
||||
} else if (TAG_Byte_Array == tagId) {
|
||||
if ("Blocks" == _data.back()->getName()) {
|
||||
_blocksId = ((TagByteArray*) _data.back())->getData();
|
||||
} else if ("Data" == _data.back()->getName()) {
|
||||
_blocksData = ((TagByteArray*) _data.back())->getData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TagIntArray::TagIntArray(std::stringstream &ss) : Tag(TAG_Int_Array, ss) {
|
||||
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
|
||||
|
||||
_data = new int[_size];
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
_data[i] = ss.get();
|
||||
}
|
||||
}
|
||||
|
||||
int retrieveData(std::string filename, std::stringstream &ss) {
|
||||
std::ifstream file(filename.c_str(), std::ios::binary);
|
||||
|
||||
int type = file.peek();
|
||||
if (type == 0x0A) {
|
||||
ss.flush();
|
||||
ss << file;
|
||||
return 0;
|
||||
}
|
||||
if (type == 0x1F) {
|
||||
return ungzip(file, ss);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ungzip(std::ifstream &file, std::stringstream &ss) {
|
||||
std::string gzipedBytes;
|
||||
gzipedBytes.clear();
|
||||
ss.flush();
|
||||
|
||||
while (!file.eof()) {
|
||||
gzipedBytes += (char) file.get();
|
||||
}
|
||||
file.close();
|
||||
|
||||
if (gzipedBytes.size() == 0) {
|
||||
ss << gzipedBytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int full_length = gzipedBytes.size();
|
||||
unsigned int half_length = gzipedBytes.size()/2;
|
||||
unsigned int uncompLength = full_length;
|
||||
|
||||
char* uncomp = (char*) calloc(sizeof(char), uncompLength);
|
||||
|
||||
z_stream strm;
|
||||
strm.next_in = (Bytef *) gzipedBytes.c_str();
|
||||
strm.avail_in = full_length;
|
||||
strm.total_out = 0;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
|
||||
bool done = false;
|
||||
|
||||
if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) {
|
||||
free(uncomp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!done) {
|
||||
// If our output buffer is too small
|
||||
if (strm.total_out >= uncompLength) {
|
||||
// Increase size of output buffer
|
||||
char* uncomp2 = (char*) calloc(sizeof(char), uncompLength + half_length);
|
||||
memcpy(uncomp2, uncomp, uncompLength);
|
||||
uncompLength += half_length;
|
||||
free(uncomp);
|
||||
uncomp = uncomp2;
|
||||
}
|
||||
|
||||
strm.next_out = (Bytef *) (uncomp + strm.total_out);
|
||||
strm.avail_out = uncompLength - strm.total_out;
|
||||
|
||||
// Inflate another chunk.
|
||||
int err = inflate (&strm, Z_SYNC_FLUSH);
|
||||
if (err == Z_STREAM_END) {
|
||||
done = true;
|
||||
} else if (err != Z_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inflateEnd (&strm) != Z_OK) {
|
||||
free(uncomp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < strm.total_out; ++i) {
|
||||
ss << uncomp[i];
|
||||
}
|
||||
free(uncomp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
175
libraries/voxels/src/Tags.h
Normal file
175
libraries/voxels/src/Tags.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// Tags.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clement Brisset on 7/3/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__Tags__
|
||||
#define __hifi__Tags__
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
|
||||
#define TAG_End 0
|
||||
#define TAG_Byte 1
|
||||
#define TAG_Short 2
|
||||
#define TAG_Int 3
|
||||
#define TAG_Long 4
|
||||
#define TAG_Float 5
|
||||
#define TAG_Double 6
|
||||
#define TAG_Byte_Array 7
|
||||
#define TAG_String 8
|
||||
#define TAG_List 9
|
||||
#define TAG_Compound 10
|
||||
#define TAG_Int_Array 11
|
||||
|
||||
int retrieveData(std::string filename, std::stringstream &ss);
|
||||
int ungzip(std::ifstream &file, std::stringstream &ss);
|
||||
|
||||
class Tag {
|
||||
public:
|
||||
Tag(int tagId, std::stringstream &ss);
|
||||
|
||||
int getTagId() const {return _tagId;}
|
||||
std::string getName () const {return _name; }
|
||||
|
||||
static Tag* readTag(int tagId, std::stringstream &ss);
|
||||
|
||||
protected:
|
||||
int _tagId;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
class TagByte : public Tag {
|
||||
public:
|
||||
TagByte(std::stringstream &ss);
|
||||
|
||||
int8_t getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int8_t _data;
|
||||
};
|
||||
|
||||
class TagShort : public Tag {
|
||||
public:
|
||||
TagShort(std::stringstream &ss);
|
||||
|
||||
int16_t getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int16_t _data;
|
||||
};
|
||||
|
||||
class TagInt : public Tag {
|
||||
public:
|
||||
TagInt(std::stringstream &ss);
|
||||
|
||||
int32_t getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int32_t _data;
|
||||
};
|
||||
|
||||
class TagLong : public Tag {
|
||||
public:
|
||||
TagLong(std::stringstream &ss);
|
||||
|
||||
int64_t getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int64_t _data;
|
||||
};
|
||||
|
||||
class TagFloat : public Tag {
|
||||
public:
|
||||
TagFloat(std::stringstream &ss);
|
||||
};
|
||||
|
||||
class TagDouble : public Tag {
|
||||
public:
|
||||
TagDouble(std::stringstream &ss);
|
||||
};
|
||||
|
||||
class TagByteArray : public Tag {
|
||||
public:
|
||||
TagByteArray(std::stringstream &ss);
|
||||
|
||||
int getSize() const {return _size;}
|
||||
char* getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int _size;
|
||||
char* _data;
|
||||
};
|
||||
|
||||
class TagString : public Tag {
|
||||
public:
|
||||
TagString(std::stringstream &ss);
|
||||
|
||||
int getSize() const {return _size;}
|
||||
std::string getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int _size;
|
||||
std::string _data;
|
||||
};
|
||||
|
||||
class TagList : public Tag {
|
||||
public:
|
||||
TagList(std::stringstream &ss);
|
||||
|
||||
int getTagId() const {return _tagId;}
|
||||
int getSize () const {return _size; }
|
||||
std::list<Tag*> getData () const {return _data; }
|
||||
|
||||
private:
|
||||
int _tagId;
|
||||
int _size;
|
||||
std::list<Tag*> _data;
|
||||
};
|
||||
|
||||
class TagCompound : public Tag {
|
||||
public:
|
||||
TagCompound(std::stringstream &ss);
|
||||
|
||||
int getSize () const {return _size; }
|
||||
std::list<Tag*> getData () const {return _data; }
|
||||
|
||||
int getWidth () const {return _width; }
|
||||
int getLength () const {return _length; }
|
||||
int getHeight () const {return _height; }
|
||||
char* getBlocksId () const {return _blocksId; }
|
||||
char* getBlocksData() const {return _blocksData;}
|
||||
|
||||
private:
|
||||
int _size;
|
||||
std::list<Tag*> _data;
|
||||
|
||||
// Specific to schematics file
|
||||
int _width;
|
||||
int _length;
|
||||
int _height;
|
||||
char* _blocksData;
|
||||
char* _blocksId;
|
||||
};
|
||||
|
||||
class TagIntArray : public Tag {
|
||||
public:
|
||||
TagIntArray(std::stringstream &ss);
|
||||
~TagIntArray() {delete _data;}
|
||||
|
||||
int getSize() const {return _size;}
|
||||
int* getData() const {return _data;}
|
||||
|
||||
private:
|
||||
int _size;
|
||||
int* _data;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Tags__) */
|
|
@ -12,11 +12,15 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
ViewFrustum::ViewFrustum() :
|
||||
|
@ -262,6 +266,7 @@ ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, floa
|
|||
|
||||
|
||||
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||
|
||||
ViewFrustum::location regularResult = INSIDE;
|
||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||
|
||||
|
@ -274,11 +279,11 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
|||
}
|
||||
|
||||
for(int i=0; i < 6; i++) {
|
||||
glm::vec3 normal = _planes[i].getNormal();
|
||||
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
const glm::vec3& boxVertexP = box.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
|
||||
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||
const glm::vec3& boxVertexN = box.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
|
@ -451,16 +456,22 @@ glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
|
|||
|
||||
const int MAX_POSSIBLE_COMBINATIONS = 43;
|
||||
|
||||
const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_SHADOW_VERTEX_COUNT+1] = {
|
||||
const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = {
|
||||
// Number of vertices in shadow polygon for the visible faces, then a list of the index of each vertice from the AABox
|
||||
|
||||
//0
|
||||
{0}, // inside
|
||||
{4, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // right
|
||||
{4, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // left
|
||||
{4, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, // left
|
||||
{0}, // n/a
|
||||
{4, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // bottom
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR},//bottom, right
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR},//bottom, left
|
||||
|
||||
//4
|
||||
{4, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, // bottom
|
||||
//5
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR },//bottom, right
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, },//bottom, left
|
||||
{0}, // n/a
|
||||
//8
|
||||
{4, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top
|
||||
{6, TOP_RIGHT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top, right
|
||||
{6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // top, left
|
||||
|
@ -469,32 +480,52 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_SHADOW_VERTEX_COUNT+1]
|
|||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{4, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front or near
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, right
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // front, left
|
||||
//16
|
||||
{4, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front or near
|
||||
|
||||
{6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front, right
|
||||
{6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, }, // front, left
|
||||
{0}, // n/a
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, // front,bottom
|
||||
{6, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR}, //front,bottom,right
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, //front,bottom,left
|
||||
//20
|
||||
{6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front,bottom
|
||||
|
||||
//21
|
||||
{6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, //front,bottom,right
|
||||
//22
|
||||
{6, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, //front,bottom,left
|
||||
{0}, // n/a
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, top
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, top, right
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // front, top, left
|
||||
|
||||
{6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // front, top
|
||||
|
||||
{6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR }, // front, top, right
|
||||
|
||||
{6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR }, // front, top, left
|
||||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{0}, // n/a
|
||||
{4, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR}, // back
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, // back, right
|
||||
{6, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR}, // back, left
|
||||
//32
|
||||
{4, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // back, right
|
||||
//34
|
||||
{6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back, left
|
||||
|
||||
|
||||
{0}, // n/a
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // back, bottom
|
||||
{6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR},//back, bottom, right
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR},//back, bottom, left
|
||||
//36
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR}, // back, bottom
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR},//back, bottom, right
|
||||
|
||||
// 38
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR },//back, bottom, left
|
||||
{0}, // n/a
|
||||
{6, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR}, // back, top
|
||||
|
||||
// 40
|
||||
{6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR}, // back, top
|
||||
|
||||
{6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, // back, top, right
|
||||
//42
|
||||
{6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left
|
||||
};
|
||||
|
||||
|
@ -508,9 +539,11 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const {
|
|||
+ ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining
|
||||
+ ((_position.z > topFarLeft.z ) << 5); // 32 = back/far | planes
|
||||
|
||||
int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
|
||||
//printLog(">>>>>>>>> ViewFrustum::getProjectedPolygon() lookup=%d\n",lookUp);
|
||||
|
||||
VoxelProjectedPolygon shadow(vertexCount);
|
||||
int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
|
||||
|
||||
VoxelProjectedPolygon projectedPolygon(vertexCount);
|
||||
|
||||
bool pointInView = true;
|
||||
bool allPointsInView = false; // assume the best, but wait till we know we have a vertex
|
||||
|
@ -523,13 +556,40 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const {
|
|||
glm::vec2 projectedPoint = projectPoint(point, pointInView);
|
||||
allPointsInView = allPointsInView && pointInView;
|
||||
anyPointsInView = anyPointsInView || pointInView;
|
||||
shadow.setVertex(i, projectedPoint);
|
||||
projectedPolygon.setVertex(i, projectedPoint);
|
||||
}
|
||||
|
||||
/***
|
||||
// Now that we've got the polygon, if it extends beyond the clipping window, then let's clip it
|
||||
// NOTE: This clipping does not improve our overall performance. It basically causes more polygons to
|
||||
// end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes()
|
||||
if ( (projectedPolygon.getMaxX() > PolygonClip::RIGHT_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) {
|
||||
|
||||
CoverageRegion::_clippedPolygons++;
|
||||
|
||||
glm::vec2* clippedVertices;
|
||||
int clippedVertexCount;
|
||||
PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount);
|
||||
|
||||
// Now reset the vertices of our projectedPolygon object
|
||||
projectedPolygon.setVertexCount(clippedVertexCount);
|
||||
for(int i = 0; i < clippedVertexCount; i++) {
|
||||
projectedPolygon.setVertex(i, clippedVertices[i]);
|
||||
}
|
||||
delete[] clippedVertices;
|
||||
|
||||
lookUp += PROJECTION_CLIPPED;
|
||||
}
|
||||
***/
|
||||
}
|
||||
// set the distance from our camera position, to the closest vertex
|
||||
float distance = glm::distance(getPosition(), box.getCenter());
|
||||
shadow.setDistance(distance);
|
||||
shadow.setAnyInView(anyPointsInView);
|
||||
shadow.setAllInView(allPointsInView);
|
||||
return shadow;
|
||||
projectedPolygon.setDistance(distance);
|
||||
projectedPolygon.setAnyInView(anyPointsInView);
|
||||
projectedPolygon.setAllInView(allPointsInView);
|
||||
projectedPolygon.setProjectionType(lookUp); // remember the projection type
|
||||
return projectedPolygon;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "AABox.h"
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
const float DEFAULT_KEYHOLE_RADIUS = 2.0f;
|
||||
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
||||
|
||||
class ViewFrustum {
|
||||
public:
|
||||
|
|
|
@ -34,7 +34,7 @@ const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL;
|
|||
typedef unsigned long int glBufferIndex;
|
||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||
|
||||
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||
const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine
|
||||
const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f;
|
||||
const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@ private:
|
|||
#endif
|
||||
glBufferIndex _glBufferIndex;
|
||||
bool _isDirty;
|
||||
long long _lastChanged;
|
||||
uint64_t _lastChanged;
|
||||
bool _shouldRender;
|
||||
bool _isStagedForDeletion;
|
||||
AABox _box;
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
const glm::vec3& getCenter() const { return _box.getCenter(); };
|
||||
const glm::vec3& getCorner() const { return _box.getCorner(); };
|
||||
float getScale() const { return _box.getSize().x; /* voxelScale = (1 / powf(2, *node->getOctalCode())); */ };
|
||||
int getLevel() const { return *_octalCode + 1; /* one based or zero based? */ };
|
||||
int getLevel() const { return *_octalCode + 1; /* one based or zero based? this doesn't correctly handle 2 byte case */ };
|
||||
|
||||
float getEnclosingRadius() const;
|
||||
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
void printDebugDetails(const char* label) const;
|
||||
bool isDirty() const { return _isDirty; };
|
||||
void clearDirtyBit() { _isDirty = false; };
|
||||
bool hasChangedSince(long long time) const { return (_lastChanged > time); };
|
||||
bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); };
|
||||
void markWithChangedTime() { _lastChanged = usecTimestampNow(); };
|
||||
void handleSubtreeChanged(VoxelTree* myTree);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,29 +10,58 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
const int MAX_SHADOW_VERTEX_COUNT = 6;
|
||||
|
||||
typedef glm::vec2 ShadowVertices[MAX_SHADOW_VERTEX_COUNT];
|
||||
// there's a max of 6 vertices of a project polygon, and a max of twice that when clipped to the screen
|
||||
const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6;
|
||||
const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2;
|
||||
typedef glm::vec2 ProjectedVertices[MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT];
|
||||
|
||||
class BoundingBox {
|
||||
public:
|
||||
BoundingBox(glm::vec2 corner, glm::vec2 size) : corner(corner), size(size) {};
|
||||
enum { BOTTOM_LEFT, BOTTOM_RIGHT, TOP_RIGHT, TOP_LEFT, VERTEX_COUNT };
|
||||
|
||||
BoundingBox(glm::vec2 corner, glm::vec2 size) : corner(corner), size(size), _set(true) {};
|
||||
BoundingBox() : _set(false) {};
|
||||
glm::vec2 corner;
|
||||
glm::vec2 size;
|
||||
bool contains(const BoundingBox& box) const;
|
||||
bool contains(const glm::vec2& point) const;
|
||||
bool pointInside(const glm::vec2& point) const { return contains(point); };
|
||||
|
||||
void explandToInclude(const BoundingBox& box);
|
||||
|
||||
float area() const { return size.x * size.y; };
|
||||
|
||||
int getVertexCount() const { return VERTEX_COUNT; };
|
||||
glm::vec2 getVertex(int vertexNumber) const;
|
||||
|
||||
BoundingBox topHalf() const;
|
||||
BoundingBox bottomHalf() const;
|
||||
BoundingBox leftHalf() const;
|
||||
BoundingBox rightHalf() const;
|
||||
|
||||
float getMaxX() const { return corner.x + size.x; }
|
||||
float getMaxY() const { return corner.y + size.y; }
|
||||
float getMinX() const { return corner.x; }
|
||||
float getMinY() const { return corner.y; }
|
||||
|
||||
void printDebugDetails(const char* label=NULL) const;
|
||||
private:
|
||||
bool _set;
|
||||
};
|
||||
|
||||
const int PROJECTION_RIGHT = 1;
|
||||
const int PROJECTION_LEFT = 2;
|
||||
const int PROJECTION_BOTTOM = 4;
|
||||
const int PROJECTION_TOP = 8;
|
||||
const int PROJECTION_NEAR = 16;
|
||||
const int PROJECTION_FAR = 32;
|
||||
const int PROJECTION_CLIPPED = 64;
|
||||
|
||||
class VoxelProjectedPolygon {
|
||||
|
||||
public:
|
||||
VoxelProjectedPolygon(const BoundingBox& box);
|
||||
|
||||
VoxelProjectedPolygon(int vertexCount = 0) :
|
||||
_vertexCount(vertexCount),
|
||||
_maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
|
||||
|
@ -40,22 +69,33 @@ public:
|
|||
{ };
|
||||
|
||||
~VoxelProjectedPolygon() { };
|
||||
const ShadowVertices& getVerices() const { return _vertices; };
|
||||
const ProjectedVertices& getVertices() const { return _vertices; };
|
||||
const glm::vec2& getVertex(int i) const { return _vertices[i]; };
|
||||
void setVertex(int vertex, const glm::vec2& point);
|
||||
int getVertexCount() const { return _vertexCount; };
|
||||
void setVertexCount(int vertexCount) { _vertexCount = vertexCount; };
|
||||
|
||||
float getDistance() const { return _distance; }
|
||||
void setDistance(float distance) { _distance = distance; }
|
||||
int getVertexCount() const { return _vertexCount; };
|
||||
void setVertexCount(int vertexCount) { _vertexCount = vertexCount; };
|
||||
float getDistance() const { return _distance; }
|
||||
void setDistance(float distance) { _distance = distance; }
|
||||
bool getAnyInView() const { return _anyInView; };
|
||||
void setAnyInView(bool anyInView) { _anyInView = anyInView; };
|
||||
bool getAllInView() const { return _allInView; };
|
||||
void setAllInView(bool allInView) { _allInView = allInView; };
|
||||
void setProjectionType(unsigned char type) { _projectionType = type; };
|
||||
unsigned char getProjectionType() const { return _projectionType; };
|
||||
|
||||
bool getAnyInView() const { return _anyInView; };
|
||||
void setAnyInView(bool anyInView) { _anyInView = anyInView; };
|
||||
bool getAllInView() const { return _allInView; };
|
||||
void setAllInView(bool allInView) { _allInView = allInView; };
|
||||
|
||||
bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const;
|
||||
bool occludes(const VoxelProjectedPolygon& occludee, bool checkAllInView = false) const;
|
||||
bool pointInside(const glm::vec2& point) const;
|
||||
bool occludes(const BoundingBox& occludee) const;
|
||||
bool intersects(const VoxelProjectedPolygon& testee) const;
|
||||
bool intersects(const BoundingBox& box) const;
|
||||
bool matches(const VoxelProjectedPolygon& testee) const;
|
||||
bool matches(const BoundingBox& testee) const;
|
||||
bool intersectsOnAxes(const VoxelProjectedPolygon& testee) const;
|
||||
|
||||
bool canMerge(const VoxelProjectedPolygon& that) const;
|
||||
void merge(const VoxelProjectedPolygon& that); // replaces vertices of this with new merged version
|
||||
|
||||
float getMaxX() const { return _maxX; }
|
||||
float getMaxY() const { return _maxY; }
|
||||
|
@ -67,10 +107,14 @@ public:
|
|||
};
|
||||
|
||||
void printDebugDetails() const;
|
||||
|
||||
static long pointInside_calls;
|
||||
static long occludes_calls;
|
||||
static long intersects_calls;
|
||||
|
||||
private:
|
||||
int _vertexCount;
|
||||
ShadowVertices _vertices;
|
||||
ProjectedVertices _vertices;
|
||||
float _maxX;
|
||||
float _maxY;
|
||||
float _minX;
|
||||
|
@ -78,6 +122,7 @@ private:
|
|||
float _distance;
|
||||
bool _anyInView; // if any points are in view
|
||||
bool _allInView; // if all points are in view
|
||||
unsigned char _projectionType;
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@
|
|||
#include "VoxelNode.h"
|
||||
#include "VoxelNodeBag.h"
|
||||
#include "CoverageMap.h"
|
||||
#include "PointerStack.h"
|
||||
|
||||
// Callback function, for recuseTreeWithOperation
|
||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
||||
|
@ -36,6 +37,7 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
|
|||
class EncodeBitstreamParams {
|
||||
public:
|
||||
int maxEncodeLevel;
|
||||
int maxLevelReached;
|
||||
const ViewFrustum* viewFrustum;
|
||||
bool includeColor;
|
||||
bool includeExistsBits;
|
||||
|
@ -43,11 +45,13 @@ public:
|
|||
bool deltaViewFrustum;
|
||||
const ViewFrustum* lastViewFrustum;
|
||||
bool wantOcclusionCulling;
|
||||
long childWasInViewDiscarded;
|
||||
|
||||
CoverageMap* map;
|
||||
|
||||
EncodeBitstreamParams(
|
||||
int maxEncodeLevel = INT_MAX,
|
||||
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
bool includeColor = WANT_COLOR,
|
||||
bool includeExistsBits = WANT_EXISTS_BITS,
|
||||
int chopLevels = 0,
|
||||
|
@ -55,8 +59,8 @@ public:
|
|||
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
bool wantOcclusionCulling= NO_OCCLUSION_CULLING,
|
||||
CoverageMap* map = IGNORE_COVERAGE_MAP) :
|
||||
|
||||
maxEncodeLevel (maxEncodeLevel),
|
||||
maxLevelReached (0),
|
||||
viewFrustum (viewFrustum),
|
||||
includeColor (includeColor),
|
||||
includeExistsBits (includeExistsBits),
|
||||
|
@ -64,6 +68,7 @@ public:
|
|||
deltaViewFrustum (deltaViewFrustum),
|
||||
lastViewFrustum (lastViewFrustum),
|
||||
wantOcclusionCulling(wantOcclusionCulling),
|
||||
childWasInViewDiscarded(0),
|
||||
map (map)
|
||||
{}
|
||||
};
|
||||
|
@ -135,6 +140,8 @@ public:
|
|||
bool readFromSVOFile(const char* filename);
|
||||
// reads voxels from square image with alpha as a Y-axis
|
||||
bool readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension);
|
||||
bool readFromSchematicFile(const char* filename);
|
||||
void computeBlockColor(int id, int data, int& r, int& g, int& b, int& create);
|
||||
|
||||
unsigned long getVoxelCount();
|
||||
|
||||
|
@ -146,6 +153,11 @@ public:
|
|||
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
||||
void recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation,
|
||||
const glm::vec3& point, void* extraData);
|
||||
|
||||
|
||||
void recurseTreeWithOperationDistanceSortedTimed(PointerStack* stackOfNodes, long allowedTime,
|
||||
RecurseVoxelTreeOperation operation,
|
||||
const glm::vec3& point, void* extraData);
|
||||
|
||||
private:
|
||||
void deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraData);
|
||||
|
@ -170,6 +182,7 @@ private:
|
|||
bool _shouldReaverage;
|
||||
};
|
||||
|
||||
int boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
||||
float boundaryDistanceSquaredForRenderLevel(unsigned int renderLevel);
|
||||
|
||||
#endif /* defined(__hifi__VoxelTree__) */
|
||||
|
|
|
@ -50,9 +50,8 @@ public:
|
|||
bool getViewSent() const { return _viewSent; };
|
||||
void setViewSent(bool viewSent) { _viewSent = viewSent; }
|
||||
|
||||
long long getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
|
||||
void setLastTimeBagEmpty(long long lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
|
||||
|
||||
uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
|
||||
void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
|
||||
|
||||
private:
|
||||
VoxelNodeData(const VoxelNodeData &);
|
||||
|
@ -67,7 +66,7 @@ private:
|
|||
int _maxLevelReachedInLastSearch;
|
||||
ViewFrustum _currentViewFrustum;
|
||||
ViewFrustum _lastKnownViewFrustum;
|
||||
long long _lastTimeBagEmpty;
|
||||
uint64_t _lastTimeBagEmpty;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo";
|
||||
const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo";
|
||||
const long long VOXEL_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||
const int VOXEL_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||
|
||||
const int VOXEL_LISTEN_PORT = 40106;
|
||||
|
||||
|
@ -110,134 +110,6 @@ void eraseVoxelTreeAndCleanupNodeVisitData() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Version of voxel distributor that sends each LOD level at a time
|
||||
void resInVoxelDistributor(NodeList* nodeList,
|
||||
NodeList::iterator& node,
|
||||
VoxelNodeData* nodeData) {
|
||||
ViewFrustum viewFrustum = nodeData->getCurrentViewFrustum();
|
||||
bool searchReset = false;
|
||||
int searchLoops = 0;
|
||||
int searchLevelWas = nodeData->getMaxSearchLevel();
|
||||
long long start = usecTimestampNow();
|
||||
while (!searchReset && nodeData->nodeBag.isEmpty()) {
|
||||
searchLoops++;
|
||||
|
||||
searchLevelWas = nodeData->getMaxSearchLevel();
|
||||
int maxLevelReached = serverTree.searchForColoredNodes(nodeData->getMaxSearchLevel(), serverTree.rootNode,
|
||||
viewFrustum, nodeData->nodeBag);
|
||||
nodeData->setMaxLevelReached(maxLevelReached);
|
||||
|
||||
// If nothing got added, then we bump our levels.
|
||||
if (nodeData->nodeBag.isEmpty()) {
|
||||
if (nodeData->getMaxLevelReached() < nodeData->getMaxSearchLevel()) {
|
||||
nodeData->resetMaxSearchLevel();
|
||||
searchReset = true;
|
||||
} else {
|
||||
nodeData->incrementMaxSearchLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
long long end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start)/1000;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
int elapsedsec = (end - start)/1000000;
|
||||
printf("WARNING! searchForColoredNodes() took %d seconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedsec, nodeData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
} else {
|
||||
printf("WARNING! searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedmsec, nodeData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
}
|
||||
} else if (::debugVoxelSending) {
|
||||
printf("searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedmsec, nodeData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
}
|
||||
|
||||
|
||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||
if (!nodeData->nodeBag.isEmpty()) {
|
||||
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
|
||||
int bytesWritten = 0;
|
||||
int packetsSentThisInterval = 0;
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
long long start = usecTimestampNow();
|
||||
|
||||
bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) {
|
||||
if (!nodeData->nodeBag.isEmpty()) {
|
||||
VoxelNode* subTree = nodeData->nodeBag.extract();
|
||||
|
||||
EncodeBitstreamParams params(nodeData->getMaxSearchLevel(), &viewFrustum,
|
||||
nodeData->getWantColor(), WANT_EXISTS_BITS);
|
||||
|
||||
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||
nodeData->nodeBag, params);
|
||||
|
||||
if (nodeData->getAvailable() >= bytesWritten) {
|
||||
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
} else {
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
trueBytesSent += nodeData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
nodeData->resetVoxelPacket();
|
||||
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
}
|
||||
} else {
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
trueBytesSent += nodeData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
nodeData->resetVoxelPacket();
|
||||
|
||||
}
|
||||
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
|
||||
}
|
||||
}
|
||||
// send the environment packets
|
||||
if (shouldSendEnvironments) {
|
||||
int envPacketLength = 1;
|
||||
int numBytesPacketHeader = populateTypeAndVersion(tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||
|
||||
for (int i = 0; i < sizeof(environmentData) / numBytesPacketHeader; i++) {
|
||||
envPacketLength += environmentData[i].getBroadcastData(tempOutputBuffer + envPacketLength);
|
||||
}
|
||||
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(), tempOutputBuffer, envPacketLength);
|
||||
trueBytesSent += envPacketLength;
|
||||
truePacketsSent++;
|
||||
}
|
||||
long long end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start)/1000;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
int elapsedsec = (end - start)/1000000;
|
||||
printf("WARNING! packetLoop() took %d seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, nodeData->nodeBag.count());
|
||||
} else {
|
||||
printf("WARNING! packetLoop() took %d milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, nodeData->nodeBag.count());
|
||||
}
|
||||
} else if (::debugVoxelSending) {
|
||||
printf("packetLoop() took %d milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, nodeData->nodeBag.count());
|
||||
}
|
||||
|
||||
// if during this last pass, we emptied our bag, then we want to move to the next level.
|
||||
if (nodeData->nodeBag.isEmpty()) {
|
||||
if (nodeData->getMaxLevelReached() < nodeData->getMaxSearchLevel()) {
|
||||
nodeData->resetMaxSearchLevel();
|
||||
} else {
|
||||
nodeData->incrementMaxSearchLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_t treeLock;
|
||||
|
||||
// Version of voxel distributor that sends the deepest LOD level at once
|
||||
|
@ -250,10 +122,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
pthread_mutex_lock(&::treeLock);
|
||||
|
||||
int maxLevelReached = 0;
|
||||
long long start = usecTimestampNow();
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
// FOR NOW... node tells us if it wants to receive only view frustum deltas
|
||||
bool wantDelta = nodeData->getWantDelta();
|
||||
bool wantDelta = viewFrustumChanged && nodeData->getWantDelta();
|
||||
const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL;
|
||||
|
||||
if (::debugVoxelSending) {
|
||||
|
@ -269,10 +141,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
if (::debugVoxelSending) {
|
||||
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
|
||||
long long now = usecTimestampNow();
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (nodeData->getLastTimeBagEmpty() > 0) {
|
||||
float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f;
|
||||
|
||||
if (viewFrustumChanged) {
|
||||
printf("viewFrustumChanged resetting after elapsed time to send scene = %f seconds", elapsedSceneSend);
|
||||
} else {
|
||||
|
@ -306,9 +177,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
} else {
|
||||
nodeData->nodeBag.insert(serverTree.rootNode);
|
||||
}
|
||||
|
||||
}
|
||||
long long end = usecTimestampNow();
|
||||
uint64_t end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start)/1000;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
|
@ -331,12 +201,12 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
int packetsSentThisInterval = 0;
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
long long start = usecTimestampNow();
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) {
|
||||
// Check to see if we're taking too long, and if so bail early...
|
||||
long long now = usecTimestampNow();
|
||||
uint64_t now = usecTimestampNow();
|
||||
long elapsedUsec = (now - start);
|
||||
long elapsedUsecPerPacket = (truePacketsSent == 0) ? 0 : (elapsedUsec / truePacketsSent);
|
||||
long usecRemaining = (VOXEL_SEND_INTERVAL_USECS - elapsedUsec);
|
||||
|
@ -352,7 +222,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
|
||||
if (!nodeData->nodeBag.isEmpty()) {
|
||||
VoxelNode* subTree = nodeData->nodeBag.extract();
|
||||
|
||||
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
|
||||
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
|
||||
|
||||
|
@ -362,12 +231,16 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
|
||||
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||
nodeData->nodeBag, params);
|
||||
|
||||
if (::debugVoxelSending && wantDelta) {
|
||||
printf("encodeTreeBitstream() childWasInViewDiscarded=%ld\n", params.childWasInViewDiscarded);
|
||||
}
|
||||
|
||||
if (nodeData->getAvailable() >= bytesWritten) {
|
||||
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
} else {
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
trueBytesSent += nodeData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
|
@ -377,7 +250,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
} else {
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
trueBytesSent += nodeData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
nodeData->resetVoxelPacket();
|
||||
|
@ -401,7 +274,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
truePacketsSent++;
|
||||
}
|
||||
|
||||
long long end = usecTimestampNow();
|
||||
uint64_t end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start)/1000;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
|
@ -422,6 +295,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
if (nodeData->nodeBag.isEmpty()) {
|
||||
nodeData->updateLastKnownViewFrustum();
|
||||
nodeData->setViewSent(true);
|
||||
if (::debugVoxelSending) {
|
||||
nodeData->map.printStats();
|
||||
}
|
||||
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
||||
}
|
||||
|
||||
|
@ -430,10 +306,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
pthread_mutex_unlock(&::treeLock);
|
||||
}
|
||||
|
||||
long long lastPersistVoxels = 0;
|
||||
uint64_t lastPersistVoxels = 0;
|
||||
void persistVoxelsWhenDirty() {
|
||||
long long now = usecTimestampNow();
|
||||
long long sinceLastTime = (now - ::lastPersistVoxels) / 1000;
|
||||
uint64_t now = usecTimestampNow();
|
||||
int sinceLastTime = (now - ::lastPersistVoxels) / 1000;
|
||||
|
||||
// check the dirty bit and persist here...
|
||||
if (::wantVoxelPersist && ::serverTree.isDirty() && sinceLastTime > VOXEL_PERSIST_INTERVAL) {
|
||||
|
@ -468,17 +344,12 @@ void *distributeVoxelsToListeners(void *args) {
|
|||
if (::debugVoxelSending) {
|
||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||
}
|
||||
|
||||
if (nodeData->getWantResIn()) {
|
||||
resInVoxelDistributor(nodeList, node, nodeData);
|
||||
} else {
|
||||
deepestLevelVoxelDistributor(nodeList, node, nodeData, viewFrustumChanged);
|
||||
}
|
||||
deepestLevelVoxelDistributor(nodeList, node, nodeData, viewFrustumChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// dynamically sleep until we need to fire off the next set of voxels
|
||||
long long usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime));
|
||||
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime));
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
|
@ -766,3 +637,5 @@ int main(int argc, const char * argv[]) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue