mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-14 02:06:48 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into lemon
This commit is contained in:
commit
303cade547
96 changed files with 1659 additions and 863 deletions
|
@ -386,8 +386,7 @@ void Agent::sendAvatarBillboardPacket() {
|
|||
void Agent::processAgentAvatarAndAudio(float deltaTime) {
|
||||
if (!_scriptEngine->isFinished() && _isAvatar) {
|
||||
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||
const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE)
|
||||
/ (1000 * 1000)) + 0.5);
|
||||
const int SCRIPT_AUDIO_BUFFER_SAMPLES = AudioConstants::SAMPLE_RATE / SCRIPT_FPS + 0.5;
|
||||
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
|
||||
|
||||
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
|
||||
|
|
|
@ -141,6 +141,16 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by
|
|||
}
|
||||
}
|
||||
|
||||
void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
viewOut = _currentViewFrustum;
|
||||
}
|
||||
|
||||
void OctreeQueryNode::copyLastKnownViewFrustum(ViewFrustum& viewOut) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
viewOut = _lastKnownViewFrustum;
|
||||
}
|
||||
|
||||
bool OctreeQueryNode::updateCurrentViewFrustum() {
|
||||
// if shutting down, return immediately
|
||||
if (_isShuttingDown) {
|
||||
|
@ -171,11 +181,13 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
|
|||
}
|
||||
|
||||
|
||||
// if there has been a change, then recalculate
|
||||
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
|
||||
_currentViewFrustum = newestViewFrustum;
|
||||
_currentViewFrustum.calculate();
|
||||
currentViewFrustumChanged = true;
|
||||
{ // if there has been a change, then recalculate
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
|
||||
_currentViewFrustum = newestViewFrustum;
|
||||
_currentViewFrustum.calculate();
|
||||
currentViewFrustumChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for LOD changes from the client
|
||||
|
@ -219,11 +231,14 @@ void OctreeQueryNode::updateLastKnownViewFrustum() {
|
|||
return;
|
||||
}
|
||||
|
||||
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
|
||||
|
||||
if (frustumChanges) {
|
||||
// save our currentViewFrustum into our lastKnownViewFrustum
|
||||
_lastKnownViewFrustum = _currentViewFrustum;
|
||||
if (frustumChanges) {
|
||||
// save our currentViewFrustum into our lastKnownViewFrustum
|
||||
_lastKnownViewFrustum = _currentViewFrustum;
|
||||
}
|
||||
}
|
||||
|
||||
// save that we know the view has been sent.
|
||||
|
@ -237,15 +252,13 @@ bool OctreeQueryNode::moveShouldDump() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition();
|
||||
glm::vec3 newPosition = _currentViewFrustum.getPosition();
|
||||
|
||||
// theoretically we could make this slightly larger but relative to avatar scale.
|
||||
const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f;
|
||||
if (glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP;
|
||||
}
|
||||
|
||||
void OctreeQueryNode::dumpOutOfView() {
|
||||
|
@ -257,8 +270,10 @@ void OctreeQueryNode::dumpOutOfView() {
|
|||
int stillInView = 0;
|
||||
int outOfView = 0;
|
||||
OctreeElementBag tempBag;
|
||||
ViewFrustum viewCopy;
|
||||
copyCurrentViewFrustum(viewCopy);
|
||||
while (OctreeElementPointer elementToCheck = elementBag.extract()) {
|
||||
if (elementToCheck->isInView(_currentViewFrustum)) {
|
||||
if (elementToCheck->isInView(viewCopy)) {
|
||||
tempBag.insert(elementToCheck);
|
||||
stillInView++;
|
||||
} else {
|
||||
|
@ -267,7 +282,7 @@ void OctreeQueryNode::dumpOutOfView() {
|
|||
}
|
||||
if (stillInView > 0) {
|
||||
while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) {
|
||||
if (elementToKeepInBag->isInView(_currentViewFrustum)) {
|
||||
if (elementToKeepInBag->isInView(viewCopy)) {
|
||||
elementBag.insert(elementToKeepInBag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
|
||||
bool packetIsDuplicate() const;
|
||||
bool shouldSuppressDuplicatePacket();
|
||||
|
||||
|
||||
unsigned int getAvailable() const { return _octreePacket->bytesAvailableForWrite(); }
|
||||
int getMaxSearchLevel() const { return _maxSearchLevel; }
|
||||
void resetMaxSearchLevel() { _maxSearchLevel = 1; }
|
||||
|
@ -56,8 +56,8 @@ public:
|
|||
OctreeElementBag elementBag;
|
||||
OctreeElementExtraEncodeData extraEncodeData;
|
||||
|
||||
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; }
|
||||
ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; }
|
||||
void copyCurrentViewFrustum(ViewFrustum& viewOut) const;
|
||||
void copyLastKnownViewFrustum(ViewFrustum& viewOut) const;
|
||||
|
||||
// These are not classic setters because they are calculating and maintaining state
|
||||
// which is set asynchronously through the network receive
|
||||
|
@ -114,6 +114,8 @@ private:
|
|||
|
||||
int _maxSearchLevel { 1 };
|
||||
int _maxLevelReachedInLastSearch { 1 };
|
||||
|
||||
mutable QMutex _viewMutex { QMutex::Recursive };
|
||||
ViewFrustum _currentViewFrustum;
|
||||
ViewFrustum _lastKnownViewFrustum;
|
||||
quint64 _lastTimeBagEmpty { 0 };
|
||||
|
@ -139,7 +141,7 @@ private:
|
|||
QQueue<OCTREE_PACKET_SEQUENCE> _nackedSequenceNumbers;
|
||||
|
||||
quint64 _sceneSendStartTime = 0;
|
||||
|
||||
|
||||
std::array<char, udt::MAX_PACKET_SIZE> _lastOctreePayload;
|
||||
};
|
||||
|
||||
|
|
|
@ -338,8 +338,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
|
||||
_packetData.changeSettings(true, targetSize); // FIXME - eventually support only compressed packets
|
||||
|
||||
const ViewFrustum* lastViewFrustum = viewFrustumChanged ? &nodeData->getLastKnownViewFrustum() : NULL;
|
||||
|
||||
// If the current view frustum has changed OR we have nothing to send, then search against
|
||||
// the current view frustum for things to send.
|
||||
if (viewFrustumChanged || nodeData->elementBag.isEmpty()) {
|
||||
|
@ -417,7 +415,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
quint64 lockWaitEnd = usecTimestampNow();
|
||||
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
||||
quint64 encodeStart = usecTimestampNow();
|
||||
|
||||
|
||||
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
||||
if (!subTree) {
|
||||
return;
|
||||
|
@ -426,18 +424,22 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
|
||||
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(),
|
||||
WANT_EXISTS_BITS, DONT_CHOP, viewFrustumChanged, lastViewFrustum,
|
||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||
viewFrustumChanged,
|
||||
boundaryLevelAdjust, octreeSizeScale,
|
||||
nodeData->getLastTimeBagEmpty(),
|
||||
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
|
||||
&nodeData->extraEncodeData);
|
||||
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
||||
if (viewFrustumChanged) {
|
||||
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
||||
}
|
||||
|
||||
// Our trackSend() function is implemented by the server subclass, and will be called back
|
||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||
params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) {
|
||||
_myServer->trackSend(dataID, dataEdited, node->getUUID());
|
||||
};
|
||||
|
|
|
@ -210,9 +210,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi
|
|||
|
||||
class DeadlockWatchdogThread : public QThread {
|
||||
public:
|
||||
static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
|
||||
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
||||
static const unsigned long HEARTBEAT_REPORT_INTERVAL_USECS = 5 * USECS_PER_SECOND;
|
||||
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND;
|
||||
static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large
|
||||
static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples
|
||||
|
@ -239,8 +237,6 @@ public:
|
|||
*crashTrigger = 0xDEAD10CC;
|
||||
}
|
||||
|
||||
static void setSuppressStatus(bool suppress) { _suppressStatus = suppress; }
|
||||
|
||||
void run() override {
|
||||
while (!_quit) {
|
||||
QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
|
||||
|
@ -248,7 +244,6 @@ public:
|
|||
uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us
|
||||
uint64_t now = usecTimestampNow();
|
||||
auto lastHeartbeatAge = (now > lastHeartbeat) ? now - lastHeartbeat : 0;
|
||||
auto sinceLastReport = (now > _lastReport) ? now - _lastReport : 0;
|
||||
auto elapsedMovingAverage = _movingAverage.getAverage();
|
||||
|
||||
if (elapsedMovingAverage > _maxElapsedAverage) {
|
||||
|
@ -274,21 +269,10 @@ public:
|
|||
if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) {
|
||||
qDebug() << "DEADLOCK WATCHDOG WARNING:"
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE**"
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **"
|
||||
<< "maxElapsed:" << _maxElapsed
|
||||
<< "maxElapsedAverage:" << _maxElapsedAverage
|
||||
<< "samples:" << _movingAverage.getSamples();
|
||||
_lastReport = now;
|
||||
}
|
||||
|
||||
if (!_suppressStatus && sinceLastReport > HEARTBEAT_REPORT_INTERVAL_USECS) {
|
||||
qDebug() << "DEADLOCK WATCHDOG STATUS:"
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||
<< "maxElapsed:" << _maxElapsed
|
||||
<< "maxElapsedAverage:" << _maxElapsedAverage
|
||||
<< "samples:" << _movingAverage.getSamples();
|
||||
_lastReport = now;
|
||||
}
|
||||
|
||||
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
||||
|
@ -310,9 +294,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static std::atomic<bool> _suppressStatus;
|
||||
static std::atomic<uint64_t> _heartbeat;
|
||||
static std::atomic<uint64_t> _lastReport;
|
||||
static std::atomic<uint64_t> _maxElapsed;
|
||||
static std::atomic<int> _maxElapsedAverage;
|
||||
static ThreadSafeMovingAverage<int, HEARTBEAT_SAMPLES> _movingAverage;
|
||||
|
@ -320,17 +302,11 @@ public:
|
|||
bool _quit { false };
|
||||
};
|
||||
|
||||
std::atomic<bool> DeadlockWatchdogThread::_suppressStatus;
|
||||
std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat;
|
||||
std::atomic<uint64_t> DeadlockWatchdogThread::_lastReport;
|
||||
std::atomic<uint64_t> DeadlockWatchdogThread::_maxElapsed;
|
||||
std::atomic<int> DeadlockWatchdogThread::_maxElapsedAverage;
|
||||
ThreadSafeMovingAverage<int, DeadlockWatchdogThread::HEARTBEAT_SAMPLES> DeadlockWatchdogThread::_movingAverage;
|
||||
|
||||
void Application::toggleSuppressDeadlockWatchdogStatus(bool checked) {
|
||||
DeadlockWatchdogThread::setSuppressStatus(checked);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
class MyNativeEventFilter : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
|
@ -1505,10 +1481,17 @@ void Application::paintGL() {
|
|||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
|
||||
RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
renderArgs.setViewFrustum(_viewFrustum);
|
||||
}
|
||||
|
||||
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
|
@ -1675,7 +1658,7 @@ void Application::paintGL() {
|
|||
renderArgs._context->enableStereo(true);
|
||||
mat4 eyeOffsets[2];
|
||||
mat4 eyeProjections[2];
|
||||
auto baseProjection = renderArgs._viewFrustum->getProjection();
|
||||
auto baseProjection = renderArgs.getViewFrustum().getProjection();
|
||||
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
||||
float IPDScale = hmdInterface->getIPDScale();
|
||||
mat4 headPose = displayPlugin->getHeadPose();
|
||||
|
@ -1805,7 +1788,10 @@ void Application::resizeGL() {
|
|||
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
|
||||
DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
|
||||
// Possible change in aspect ratio
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto uiSize = displayPlugin->getRecommendedUiSize();
|
||||
|
@ -2132,6 +2118,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
|
||||
case Qt::Key_J:
|
||||
if (isShifted) {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
|
||||
|
@ -2141,6 +2128,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
|
||||
case Qt::Key_M:
|
||||
if (isShifted) {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
|
||||
|
@ -2989,7 +2977,10 @@ void Application::init() {
|
|||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
|
||||
getEntities()->init();
|
||||
getEntities()->setViewFrustum(getViewFrustum());
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
getEntities()->setViewFrustum(_viewFrustum);
|
||||
}
|
||||
|
||||
ObjectMotionState::setShapeManager(&_shapeManager);
|
||||
_physicsEngine->init();
|
||||
|
@ -3009,12 +3000,26 @@ void Application::init() {
|
|||
getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
|
||||
|
||||
_entityClipboardRenderer.init();
|
||||
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_entityClipboardRenderer.setViewFrustum(_viewFrustum);
|
||||
}
|
||||
_entityClipboardRenderer.setTree(_entityClipboard);
|
||||
|
||||
// Make sure any new sounds are loaded as soon as know about them.
|
||||
connect(tree.get(), &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||
connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||
connect(tree.get(), &EntityTree::newCollisionSoundURL, this, [this](QUrl newURL, EntityItemID id) {
|
||||
EntityTreePointer tree = getEntities()->getTree();
|
||||
if (auto entity = tree->findEntityByEntityItemID(id)) {
|
||||
auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
|
||||
entity->setCollisionSound(sound);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
|
||||
if (auto avatar = getMyAvatar()) {
|
||||
auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
|
||||
avatar->setCollisionSound(sound);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Application::updateLOD() const {
|
||||
|
@ -3212,9 +3217,12 @@ void Application::resetPhysicsReadyInformation() {
|
|||
|
||||
void Application::reloadResourceCaches() {
|
||||
resetPhysicsReadyInformation();
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
|
||||
_viewFrustum.setOrientation(glm::quat());
|
||||
}
|
||||
// Clear entities out of view frustum
|
||||
_viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
|
||||
_viewFrustum.setOrientation(glm::quat());
|
||||
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
|
||||
|
||||
DependencyManager::get<AssetClient>()->clearCache();
|
||||
|
@ -3503,7 +3511,7 @@ void Application::update(float deltaTime) {
|
|||
// actually need to calculate the view frustum planes to send these details
|
||||
// to the server.
|
||||
{
|
||||
PerformanceTimer perfTimer("loadViewFrustum");
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
}
|
||||
|
||||
|
@ -3512,6 +3520,7 @@ void Application::update(float deltaTime) {
|
|||
// Update my voxel servers with my current voxel query...
|
||||
{
|
||||
PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
PerformanceTimer perfTimer("queryOctree");
|
||||
quint64 sinceLastQuery = now - _lastQueriedTime;
|
||||
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
|
||||
|
@ -3623,14 +3632,16 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
//qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
|
||||
bool wantExtraDebugging = getLogger()->extraDebugging();
|
||||
|
||||
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
|
||||
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
||||
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
||||
_octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
|
||||
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
||||
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
||||
ViewFrustum viewFrustum;
|
||||
copyViewFrustum(viewFrustum);
|
||||
_octreeQuery.setCameraPosition(viewFrustum.getPosition());
|
||||
_octreeQuery.setCameraOrientation(viewFrustum.getOrientation());
|
||||
_octreeQuery.setCameraFov(viewFrustum.getFieldOfView());
|
||||
_octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio());
|
||||
_octreeQuery.setCameraNearClip(viewFrustum.getNearClip());
|
||||
_octreeQuery.setCameraFarClip(viewFrustum.getFarClip());
|
||||
_octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
|
||||
_octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius());
|
||||
_octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius());
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
|
||||
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
|
||||
|
@ -3666,7 +3677,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
rootDetails.y * TREE_SCALE,
|
||||
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
|
||||
rootDetails.s * TREE_SCALE);
|
||||
if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
|
||||
if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
|
||||
inViewServers++;
|
||||
}
|
||||
}
|
||||
|
@ -3732,11 +3743,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
rootDetails.s * TREE_SCALE);
|
||||
|
||||
|
||||
inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds);
|
||||
} else {
|
||||
if (wantExtraDebugging) {
|
||||
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
|
||||
}
|
||||
inView = viewFrustum.cubeIntersectsKeyhole(serverBounds);
|
||||
} else if (wantExtraDebugging) {
|
||||
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3827,6 +3836,7 @@ QRect Application::getDesirableApplicationGeometry() const {
|
|||
// or the "myCamera".
|
||||
//
|
||||
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||
PerformanceTimer perfTimer("loadViewFrustum");
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
// We will use these below, from either the camera or head vectors calculated above
|
||||
viewFrustum.setProjection(camera.getProjection());
|
||||
|
@ -3855,7 +3865,8 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
|
||||
} else {
|
||||
pickPoint /= getCanvasSize();
|
||||
getViewFrustum()->computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -3868,44 +3879,19 @@ glm::vec3 Application::getAvatarPosition() const {
|
|||
return getMyAvatar()->getPosition();
|
||||
}
|
||||
|
||||
ViewFrustum* Application::getViewFrustum() {
|
||||
#ifdef DEBUG
|
||||
if (QThread::currentThread() == activeRenderingThread) {
|
||||
// FIXME, figure out a better way to do this
|
||||
//qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
|
||||
}
|
||||
#endif
|
||||
return &_viewFrustum;
|
||||
void Application::copyViewFrustum(ViewFrustum& viewOut) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
viewOut = _viewFrustum;
|
||||
}
|
||||
|
||||
const ViewFrustum* Application::getViewFrustum() const {
|
||||
#ifdef DEBUG
|
||||
if (QThread::currentThread() == activeRenderingThread) {
|
||||
// FIXME, figure out a better way to do this
|
||||
//qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
|
||||
}
|
||||
#endif
|
||||
return &_viewFrustum;
|
||||
void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
viewOut = _displayViewFrustum;
|
||||
}
|
||||
|
||||
ViewFrustum* Application::getDisplayViewFrustum() {
|
||||
#ifdef DEBUG
|
||||
if (QThread::currentThread() != activeRenderingThread) {
|
||||
// FIXME, figure out a better way to do this
|
||||
// qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
|
||||
}
|
||||
#endif
|
||||
return &_displayViewFrustum;
|
||||
}
|
||||
|
||||
const ViewFrustum* Application::getDisplayViewFrustum() const {
|
||||
#ifdef DEBUG
|
||||
if (QThread::currentThread() != activeRenderingThread) {
|
||||
// FIXME, figure out a better way to do this
|
||||
// qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
|
||||
}
|
||||
#endif
|
||||
return &_displayViewFrustum;
|
||||
void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
viewOut = _shadowViewFrustum;
|
||||
}
|
||||
|
||||
// WorldBox Render Data & rendering functions
|
||||
|
@ -3970,7 +3956,7 @@ namespace render {
|
|||
auto skybox = skyStage->getSkybox();
|
||||
if (skybox) {
|
||||
PerformanceTimer perfTimer("skybox");
|
||||
skybox->render(batch, *(args->_viewFrustum));
|
||||
skybox->render(batch, args->getViewFrustum());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4014,7 +4000,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
|
||||
|
||||
// load the view frustum
|
||||
loadViewFrustum(theCamera, _displayViewFrustum);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
loadViewFrustum(theCamera, _displayViewFrustum);
|
||||
}
|
||||
|
||||
// TODO fix shadows and make them use the GPU library
|
||||
|
||||
|
@ -4082,7 +4071,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
{
|
||||
PerformanceTimer perfTimer("EngineRun");
|
||||
|
||||
renderArgs->_viewFrustum = getDisplayViewFrustum();
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
renderArgs->setViewFrustum(_displayViewFrustum);
|
||||
}
|
||||
_renderEngine->getRenderContext()->args = renderArgs;
|
||||
|
||||
// Before the deferred pass, let's try to use the render engine
|
||||
|
@ -5212,10 +5204,10 @@ void Application::updateInputModes() {
|
|||
}
|
||||
|
||||
mat4 Application::getEyeProjection(int eye) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
if (isHMDMode()) {
|
||||
return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection());
|
||||
}
|
||||
|
||||
return _viewFrustum.getProjection();
|
||||
}
|
||||
|
||||
|
|
|
@ -128,14 +128,12 @@ public:
|
|||
Camera* getCamera() { return &_myCamera; }
|
||||
const Camera* getCamera() const { return &_myCamera; }
|
||||
// Represents the current view frustum of the avatar.
|
||||
ViewFrustum* getViewFrustum();
|
||||
const ViewFrustum* getViewFrustum() const;
|
||||
void copyViewFrustum(ViewFrustum& viewOut) const;
|
||||
// Represents the view frustum of the current rendering pass,
|
||||
// which might be different from the viewFrustum, i.e. shadowmap
|
||||
// passes, mirror window passes, etc
|
||||
ViewFrustum* getDisplayViewFrustum();
|
||||
const ViewFrustum* getDisplayViewFrustum() const;
|
||||
ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; }
|
||||
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
|
||||
void copyShadowViewFrustum(ViewFrustum& viewOut) const override;
|
||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||
EntityTreeRenderer* getEntities() const { return DependencyManager::get<EntityTreeRenderer>().data(); }
|
||||
QUndoStack* getUndoStack() { return &_undoStack; }
|
||||
|
@ -169,7 +167,7 @@ public:
|
|||
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
|
||||
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
|
||||
|
||||
virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); }
|
||||
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); }
|
||||
virtual QThread* getMainThread() override { return thread(); }
|
||||
virtual PickRay computePickRay(float x, float y) const override;
|
||||
virtual glm::vec3 getAvatarPosition() const override;
|
||||
|
@ -255,7 +253,6 @@ public slots:
|
|||
|
||||
void resetSensors(bool andReload = false);
|
||||
void setActiveFaceTracker() const;
|
||||
void toggleSuppressDeadlockWatchdogStatus(bool checked);
|
||||
|
||||
#ifdef HAVE_IVIEWHMD
|
||||
void setActiveEyeTracker();
|
||||
|
@ -414,6 +411,7 @@ private:
|
|||
EntityTreeRenderer _entityClipboardRenderer;
|
||||
EntityTreePointer _entityClipboard;
|
||||
|
||||
mutable QMutex _viewMutex { QMutex::Recursive };
|
||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
|
||||
ViewFrustum _displayViewFrustum;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
|
||||
#include <SettingHandle.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <Util.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
@ -216,7 +217,7 @@ QString LODManager::getLODFeedbackText() {
|
|||
bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
|
||||
// FIXME - eventually we want to use the render accuracy as an indicator for the level of detail
|
||||
// to use in rendering.
|
||||
float renderAccuracy = args->_viewFrustum->calculateRenderAccuracy(bounds, args->_sizeScale, args->_boundaryLevelAdjust);
|
||||
float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust);
|
||||
return (renderAccuracy > 0.0f);
|
||||
};
|
||||
|
||||
|
@ -228,7 +229,6 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
|||
_boundaryLevelAdjust = boundaryLevelAdjust;
|
||||
}
|
||||
|
||||
|
||||
void LODManager::loadSettings() {
|
||||
setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get());
|
||||
setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get());
|
||||
|
@ -239,4 +239,3 @@ void LODManager::saveSettings() {
|
|||
hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -568,8 +568,6 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings);
|
||||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::LogExtraTimings);
|
||||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings);
|
||||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SupressDeadlockWatchdogStatus, 0, false,
|
||||
qApp, SLOT(toggleSuppressDeadlockWatchdogStatus(bool)));
|
||||
|
||||
|
||||
// Developer > Audio >>>
|
||||
|
|
|
@ -182,7 +182,6 @@ namespace MenuOption {
|
|||
const QString Stats = "Stats";
|
||||
const QString StopAllScripts = "Stop All Scripts";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString SupressDeadlockWatchdogStatus = "Supress Deadlock Watchdog Status";
|
||||
const QString ThirdPerson = "Third Person";
|
||||
const QString ThreePointCalibration = "3 Point Calibration";
|
||||
const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Basic2DWindowOpenGLDisplayPlugin.cpp
|
||||
|
|
|
@ -194,8 +194,8 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
batch.setViewTransform(Transform());
|
||||
batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection());
|
||||
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) *
|
||||
batch.setProjectionTransform(renderArgs->getViewFrustum().getProjection());
|
||||
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->getViewFrustum().getOrientation()) *
|
||||
quat(vec3(TILT, 0, 0))));
|
||||
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <LODManager.h>
|
||||
#include <NodeList.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -171,7 +172,10 @@ void Avatar::simulate(float deltaTime) {
|
|||
// update the shouldAnimate flag to match whether or not we will render the avatar.
|
||||
const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
|
||||
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
|
||||
float visibility = qApp->getViewFrustum()->calculateRenderAccuracy(getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
||||
ViewFrustum viewFrustum;
|
||||
qApp->copyViewFrustum(viewFrustum);
|
||||
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
|
||||
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
||||
if (!_shouldAnimate) {
|
||||
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
|
||||
_shouldAnimate = true;
|
||||
|
@ -184,8 +188,9 @@ void Avatar::simulate(float deltaTime) {
|
|||
|
||||
// simple frustum check
|
||||
float boundingRadius = getBoundingRadius();
|
||||
bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius);
|
||||
bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
|
||||
qApp->copyDisplayViewFrustum(viewFrustum);
|
||||
bool avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
|
||||
bool avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
|
||||
|
||||
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
|
||||
{
|
||||
|
@ -381,17 +386,16 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
}
|
||||
}
|
||||
|
||||
// simple frustum check
|
||||
float boundingRadius = getBoundingRadius();
|
||||
ViewFrustum* frustum = nullptr;
|
||||
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
frustum = qApp->getShadowViewFrustum();
|
||||
} else {
|
||||
frustum = qApp->getDisplayViewFrustum();
|
||||
}
|
||||
|
||||
if (!frustum->sphereIntersectsFrustum(getPosition(), boundingRadius)) {
|
||||
return;
|
||||
{ // simple frustum check
|
||||
ViewFrustum frustum;
|
||||
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
qApp->copyShadowViewFrustum(frustum);
|
||||
} else {
|
||||
qApp->copyDisplayViewFrustum(frustum);
|
||||
}
|
||||
if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 toTarget = cameraPosition - getPosition();
|
||||
|
@ -413,7 +417,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||
|
||||
// render body
|
||||
renderBody(renderArgs, frustum, glowLevel);
|
||||
renderBody(renderArgs, glowLevel);
|
||||
|
||||
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||
// add local lights
|
||||
|
@ -502,9 +506,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
|
||||
auto cameraMode = qApp->getCamera()->getMode();
|
||||
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
||||
auto& frustum = *renderArgs->_viewFrustum;
|
||||
auto& frustum = renderArgs->getViewFrustum();
|
||||
auto textPosition = getDisplayNamePosition();
|
||||
|
||||
if (frustum.pointIntersectsFrustum(textPosition)) {
|
||||
renderDisplayName(batch, frustum, textPosition);
|
||||
}
|
||||
|
@ -553,7 +556,7 @@ void Avatar::fixupModelsInScene() {
|
|||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
|
||||
void Avatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
|
||||
fixupModelsInScene();
|
||||
getHead()->renderLookAts(renderArgs);
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ protected:
|
|||
|
||||
Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
|
||||
virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene();
|
||||
|
||||
|
|
|
@ -93,13 +93,13 @@ void AvatarActionHold::prepareForPhysicsSimulation() {
|
|||
activateBody(true);
|
||||
}
|
||||
|
||||
std::shared_ptr<Avatar> AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity) {
|
||||
bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity) {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID));
|
||||
|
||||
if (!holdingAvatar) {
|
||||
return holdingAvatar;
|
||||
return false;;
|
||||
}
|
||||
|
||||
withReadLock([&]{
|
||||
|
@ -171,62 +171,17 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(float deltaTimeStep, glm::qu
|
|||
linearVelocity = linearVelocity + glm::cross(angularVelocity, position - palmPosition);
|
||||
});
|
||||
|
||||
return holdingAvatar;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
||||
glm::quat rotation;
|
||||
glm::vec3 position;
|
||||
glm::vec3 linearVelocity;
|
||||
glm::vec3 angularVelocity;
|
||||
bool valid = false;
|
||||
int holdCount = 0;
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
}
|
||||
QList<EntityActionPointer> holdActions = ownerEntity->getActionsOfType(ACTION_TYPE_HOLD);
|
||||
foreach (EntityActionPointer action, holdActions) {
|
||||
std::shared_ptr<AvatarActionHold> holdAction = std::static_pointer_cast<AvatarActionHold>(action);
|
||||
glm::quat rotationForAction;
|
||||
glm::vec3 positionForAction;
|
||||
glm::vec3 linearVelocityForAction, angularVelocityForAction;
|
||||
std::shared_ptr<Avatar> holdingAvatar = holdAction->getTarget(deltaTimeStep, rotationForAction, positionForAction, linearVelocityForAction, angularVelocityForAction);
|
||||
if (holdingAvatar) {
|
||||
holdCount ++;
|
||||
if (holdAction.get() == this) {
|
||||
// only use the rotation for this action
|
||||
valid = true;
|
||||
rotation = rotationForAction;
|
||||
}
|
||||
|
||||
position += positionForAction;
|
||||
linearVelocity += linearVelocityForAction;
|
||||
angularVelocity += angularVelocityForAction;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid && holdCount > 0) {
|
||||
position /= holdCount;
|
||||
linearVelocity /= holdCount;
|
||||
angularVelocity /= holdCount;
|
||||
|
||||
withWriteLock([&]{
|
||||
_positionalTarget = position;
|
||||
_rotationalTarget = rotation;
|
||||
_linearVelocityTarget = linearVelocity;
|
||||
_angularVelocityTarget = angularVelocity;
|
||||
_positionalTargetSet = true;
|
||||
_rotationalTargetSet = true;
|
||||
_active = true;
|
||||
});
|
||||
if (_kinematic) {
|
||||
if (_kinematic) {
|
||||
if (prepareForSpringUpdate(deltaTimeStep)) {
|
||||
doKinematicUpdate(deltaTimeStep);
|
||||
} else {
|
||||
forceBodyNonStatic();
|
||||
ObjectActionSpring::updateActionWorker(deltaTimeStep);
|
||||
}
|
||||
} else {
|
||||
forceBodyNonStatic();
|
||||
ObjectActionSpring::updateActionWorker(deltaTimeStep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); }
|
||||
|
||||
bool getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
|
||||
std::shared_ptr<Avatar> getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity);
|
||||
virtual bool getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity) override;
|
||||
|
||||
virtual void prepareForPhysicsSimulation() override;
|
||||
|
||||
|
@ -51,9 +51,6 @@ private:
|
|||
QString _hand { "right" };
|
||||
QUuid _holderID;
|
||||
|
||||
glm::vec3 _linearVelocityTarget;
|
||||
glm::vec3 _angularVelocityTarget;
|
||||
|
||||
bool _kinematic { false };
|
||||
bool _kinematicSetVelocity { false };
|
||||
bool _previousSet { false };
|
||||
|
|
|
@ -309,9 +309,11 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
// my avatar. (Other user machines will make a similar analysis and inject sound for their collisions.)
|
||||
if (collision.idA.isNull() || collision.idB.isNull()) {
|
||||
MyAvatar* myAvatar = getMyAvatar();
|
||||
const QString& collisionSoundURL = myAvatar->getCollisionSoundURL();
|
||||
if (!collisionSoundURL.isEmpty()) {
|
||||
const float velocityChange = glm::length(collision.velocityChange);
|
||||
auto collisionSound = myAvatar->getCollisionSound();
|
||||
if (collisionSound) {
|
||||
const auto characterController = myAvatar->getCharacterController();
|
||||
const float avatarVelocityChange = (characterController ? glm::length(characterController->getVelocityChange()) : 0.0f);
|
||||
const float velocityChange = glm::length(collision.velocityChange) + avatarVelocityChange;
|
||||
const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01f;
|
||||
const bool isSound = (collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION);
|
||||
|
||||
|
@ -327,7 +329,7 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
// but most avatars are roughly the same size, so let's not be so fancy yet.
|
||||
const float AVATAR_STRETCH_FACTOR = 1.0f;
|
||||
|
||||
AudioInjector::playSound(collisionSoundURL, energyFactorOfFull, AVATAR_STRETCH_FACTOR, myAvatar->getPosition());
|
||||
AudioInjector::playSound(collisionSound, energyFactorOfFull, AVATAR_STRETCH_FACTOR, myAvatar->getPosition());
|
||||
myAvatar->collisionWithEntity(collision);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -316,9 +316,6 @@ void Head::relaxLean(float deltaTime) {
|
|||
_deltaLeanForward *= relaxationFactor;
|
||||
}
|
||||
|
||||
void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum) {
|
||||
}
|
||||
|
||||
void Head::renderLookAts(RenderArgs* renderArgs) {
|
||||
renderLookAts(renderArgs, _leftEyePosition, _rightEyePosition);
|
||||
}
|
||||
|
|
|
@ -28,11 +28,10 @@ class Avatar;
|
|||
class Head : public HeadData {
|
||||
public:
|
||||
explicit Head(Avatar* owningAvatar);
|
||||
|
||||
|
||||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||
void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum);
|
||||
void setScale(float scale);
|
||||
void setPosition(glm::vec3 position) { _position = position; }
|
||||
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
|
||||
|
@ -44,7 +43,7 @@ public:
|
|||
|
||||
/// \return orientationBase+Delta
|
||||
glm::quat getFinalOrientationInLocalFrame() const;
|
||||
|
||||
|
||||
/// \return orientationBody * (orientationBase+Delta)
|
||||
glm::quat getFinalOrientationInWorldFrame() const;
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <AudioClient.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
#include <FSTReader.h>
|
||||
#include <GeometryUtil.h>
|
||||
|
@ -32,6 +31,7 @@
|
|||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <SoundCache.h>
|
||||
#include <TextRenderer3D.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <AnimDebugDraw.h>
|
||||
|
@ -97,7 +97,6 @@ MyAvatar::MyAvatar(RigPointer rig) :
|
|||
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE),
|
||||
_scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
|
||||
_motionBehaviors(AVATAR_MOTION_DEFAULTS),
|
||||
_collisionSoundURL(""),
|
||||
_characterController(this),
|
||||
_lookAtTargetAvatar(),
|
||||
_shouldRender(true),
|
||||
|
@ -546,7 +545,9 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
|||
head->setDeltaYaw(estimatedRotation.y);
|
||||
head->setDeltaRoll(estimatedRotation.z);
|
||||
} else {
|
||||
float magnifyFieldOfView = qApp->getViewFrustum()->getFieldOfView() / _realWorldFieldOfView.get();
|
||||
ViewFrustum viewFrustum;
|
||||
qApp->copyViewFrustum(viewFrustum);
|
||||
float magnifyFieldOfView = viewFrustum.getFieldOfView() / _realWorldFieldOfView.get();
|
||||
head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView);
|
||||
head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
|
||||
head->setDeltaRoll(estimatedRotation.z);
|
||||
|
@ -929,15 +930,17 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
// (We will be adding that offset to the camera position, after making some other adjustments.)
|
||||
glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
|
||||
|
||||
ViewFrustum viewFrustum;
|
||||
qApp->copyViewFrustum(viewFrustum);
|
||||
|
||||
// scale gazeOffset by IPD, if wearing an HMD.
|
||||
if (qApp->isHMDMode()) {
|
||||
glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left);
|
||||
glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right);
|
||||
glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]);
|
||||
glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]);
|
||||
auto humanSystem = qApp->getViewFrustum();
|
||||
glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal);
|
||||
glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal);
|
||||
glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal);
|
||||
glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal);
|
||||
|
||||
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
||||
float ipdScale = hmdInterface->getIPDScale();
|
||||
|
@ -951,7 +954,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
}
|
||||
|
||||
// And now we can finally add that offset to the camera.
|
||||
glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset;
|
||||
glm::vec3 corrected = viewFrustum.getPosition() + gazeOffset;
|
||||
|
||||
avatar->getHead()->setCorrectedLookAtPosition(corrected);
|
||||
|
||||
|
@ -1232,12 +1235,20 @@ void MyAvatar::clearScriptableSettings() {
|
|||
}
|
||||
|
||||
void MyAvatar::setCollisionSoundURL(const QString& url) {
|
||||
_collisionSoundURL = url;
|
||||
if (!url.isEmpty() && (url != _collisionSoundURL)) {
|
||||
emit newCollisionSoundURL(QUrl(url));
|
||||
if (url != _collisionSoundURL) {
|
||||
_collisionSoundURL = url;
|
||||
|
||||
emit newCollisionSoundURL(QUrl(_collisionSoundURL));
|
||||
}
|
||||
}
|
||||
|
||||
SharedSoundPointer MyAvatar::getCollisionSound() {
|
||||
if (!_collisionSound) {
|
||||
_collisionSound = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
|
||||
}
|
||||
return _collisionSound;
|
||||
}
|
||||
|
||||
void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
||||
const glm::vec3& translation, const glm::quat& rotation,
|
||||
float scale, bool isSoft,
|
||||
|
@ -1259,7 +1270,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
|||
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
||||
}
|
||||
|
||||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
|
||||
void MyAvatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
|
||||
|
||||
if (!_skeletonModel->isRenderable()) {
|
||||
return; // wait until all models are loaded
|
||||
|
@ -1267,11 +1278,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
|
|||
|
||||
fixupModelsInScene();
|
||||
|
||||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(renderArgs)) {
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum);
|
||||
}
|
||||
|
||||
// This is drawing the lookat vectors from our avatar to wherever we're looking.
|
||||
if (qApp->isHMDMode()) {
|
||||
glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
||||
|
@ -1352,7 +1358,6 @@ void MyAvatar::destroyAnimGraph() {
|
|||
void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
|
||||
if (_skeletonModel->initWhenReady(scene)) {
|
||||
initHeadBones();
|
||||
|
@ -1404,6 +1409,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
DebugDraw::getInstance().updateMyAvatarPos(getPosition());
|
||||
DebugDraw::getInstance().updateMyAvatarRot(getOrientation());
|
||||
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
_skeletonModel->setCauterizeBones(!shouldDrawHead);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <SettingHandle.h>
|
||||
#include <Rig.h>
|
||||
#include <Sound.h>
|
||||
|
||||
#include <controllers/Pose.h>
|
||||
|
||||
|
@ -222,6 +223,9 @@ public:
|
|||
const QString& getCollisionSoundURL() { return _collisionSoundURL; }
|
||||
void setCollisionSoundURL(const QString& url);
|
||||
|
||||
SharedSoundPointer getCollisionSound();
|
||||
void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; }
|
||||
|
||||
void clearScriptableSettings();
|
||||
|
||||
float getBoomLength() const { return _boomLength; }
|
||||
|
@ -306,7 +310,7 @@ private:
|
|||
void simulate(float deltaTime);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f) override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
|
||||
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); }
|
||||
bool getShouldRenderLocally() const { return _shouldRender; }
|
||||
|
@ -362,6 +366,8 @@ private:
|
|||
quint32 _motionBehaviors;
|
||||
QString _collisionSoundURL;
|
||||
|
||||
SharedSoundPointer _collisionSound;
|
||||
|
||||
MyCharacterController _characterController;
|
||||
|
||||
AvatarWeakPointer _lookAtTargetAvatar;
|
||||
|
|
|
@ -203,7 +203,7 @@ int main(int argc, const char* argv[]) {
|
|||
Application::shutdownPlugins();
|
||||
|
||||
qCDebug(interfaceapp, "Normal exit.");
|
||||
#ifndef DEBUG
|
||||
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
|
||||
// HACK: exit immediately (don't handle shutdown callbacks) for Release build
|
||||
_exit(exitCode);
|
||||
#endif
|
||||
|
|
|
@ -31,10 +31,12 @@ UpdateDialog::UpdateDialog(QQuickItem* parent) :
|
|||
|
||||
_releaseNotes = "";
|
||||
for (int i = latestVersion; i > currentVersion; i--) {
|
||||
QString releaseNotes = applicationUpdater.data()->getBuildData()[i]["releaseNotes"];
|
||||
releaseNotes.remove("<br />");
|
||||
releaseNotes.remove(QRegExp("^\n+"));
|
||||
_releaseNotes += "\n" + QString().sprintf("%d", i) + "\n" + releaseNotes + "\n";
|
||||
if (applicationUpdater.data()->getBuildData().contains(i)) {
|
||||
QString releaseNotes = applicationUpdater.data()->getBuildData()[i]["releaseNotes"];
|
||||
releaseNotes.remove("<br />");
|
||||
releaseNotes.remove(QRegExp("^\n+"));
|
||||
_releaseNotes += "\n" + QString().sprintf("%d", i) + "\n" + releaseNotes + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
// Get the camera position rounded to the nearest major grid line
|
||||
// This grid is for UI and should lie on worldlines
|
||||
auto cameraPosition =
|
||||
(float)_majorGridEvery * glm::round(args->_viewFrustum->getPosition() / (float)_majorGridEvery);
|
||||
(float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery);
|
||||
|
||||
position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ void LocalModelsOverlay::render(RenderArgs* args) {
|
|||
auto batch = args ->_batch;
|
||||
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(args->_viewFrustum->getPosition() + getPosition());
|
||||
transform.setTranslation(args->getViewFrustum().getPosition() + getPosition());
|
||||
batch->setViewTransform(transform);
|
||||
_entityTreeRenderer->render(args);
|
||||
transform.setTranslation(args->_viewFrustum->getPosition());
|
||||
transform.setTranslation(args->getViewFrustum().getPosition());
|
||||
batch->setViewTransform(transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,17 +365,9 @@ void AudioInjector::stopAndDeleteLater() {
|
|||
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
AudioInjector* AudioInjector::playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position) {
|
||||
if (soundUrl.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
auto soundCache = DependencyManager::get<SoundCache>();
|
||||
if (soundCache.isNull()) {
|
||||
return NULL;
|
||||
}
|
||||
SharedSoundPointer sound = soundCache->getSound(QUrl(soundUrl));
|
||||
if (sound.isNull() || !sound->isReady()) {
|
||||
return NULL;
|
||||
AudioInjector* AudioInjector::playSound(SharedSoundPointer sound, const float volume, const float stretchFactor, const glm::vec3 position) {
|
||||
if (!sound || !sound->isReady()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioInjectorOptions options;
|
||||
|
@ -385,7 +377,7 @@ AudioInjector* AudioInjector::playSound(const QString& soundUrl, const float vol
|
|||
|
||||
QByteArray samples = sound->getByteArray();
|
||||
if (stretchFactor == 1.0f) {
|
||||
return playSoundAndDelete(samples, options, NULL);
|
||||
return playSoundAndDelete(samples, options, nullptr);
|
||||
}
|
||||
|
||||
const int standardRate = AudioConstants::SAMPLE_RATE;
|
||||
|
@ -403,7 +395,7 @@ AudioInjector* AudioInjector::playSound(const QString& soundUrl, const float vol
|
|||
nInputFrames);
|
||||
|
||||
Q_UNUSED(nOutputFrames);
|
||||
return playSoundAndDelete(resampled, options, NULL);
|
||||
return playSoundAndDelete(resampled, options, nullptr);
|
||||
}
|
||||
|
||||
AudioInjector* AudioInjector::playSoundAndDelete(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface) {
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
static AudioInjector* playSoundAndDelete(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface);
|
||||
static AudioInjector* playSound(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface);
|
||||
static AudioInjector* playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position);
|
||||
static AudioInjector* playSound(SharedSoundPointer sound, const float volume, const float stretchFactor, const glm::vec3 position);
|
||||
|
||||
public slots:
|
||||
void restart();
|
||||
|
|
|
@ -237,12 +237,6 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
|
||||
_vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported();
|
||||
|
||||
// Child classes may override this in order to do things like initialize
|
||||
// libraries, etc
|
||||
if (!internalActivate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if THREADED_PRESENT
|
||||
// Start the present thread if necessary
|
||||
|
@ -258,8 +252,18 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
// Start execution
|
||||
presentThread->start();
|
||||
}
|
||||
_presentThread = presentThread.data();
|
||||
#endif
|
||||
|
||||
// Child classes may override this in order to do things like initialize
|
||||
// libraries, etc
|
||||
if (!internalActivate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This should not return until the new context has been customized
|
||||
#if THREADED_PRESENT
|
||||
|
||||
// This should not return until the new context has been customized
|
||||
// and the old context (if any) has been uncustomized
|
||||
presentThread->setNewDisplayPlugin(this);
|
||||
#else
|
||||
|
|
|
@ -103,6 +103,7 @@ protected:
|
|||
|
||||
virtual void updateFrameData();
|
||||
|
||||
QThread* _presentThread{ nullptr };
|
||||
ProgramPtr _program;
|
||||
int32_t _mvpUniform { -1 };
|
||||
int32_t _alphaUniform { -1 };
|
||||
|
|
|
@ -63,7 +63,7 @@ bool HmdDisplayPlugin::internalActivate() {
|
|||
}
|
||||
|
||||
|
||||
static const char * REPROJECTION_VS = R"VS(#version 450 core
|
||||
static const char * REPROJECTION_VS = R"VS(#version 410 core
|
||||
in vec3 Position;
|
||||
in vec2 TexCoord;
|
||||
|
||||
|
@ -78,15 +78,15 @@ void main() {
|
|||
|
||||
)VS";
|
||||
|
||||
static const GLint REPROJECTION_MATRIX_LOCATION = 0;
|
||||
static const GLint INVERSE_PROJECTION_MATRIX_LOCATION = 4;
|
||||
static const GLint PROJECTION_MATRIX_LOCATION = 12;
|
||||
static const char * REPROJECTION_FS = R"FS(#version 450 core
|
||||
static GLint REPROJECTION_MATRIX_LOCATION = -1;
|
||||
static GLint INVERSE_PROJECTION_MATRIX_LOCATION = -1;
|
||||
static GLint PROJECTION_MATRIX_LOCATION = -1;
|
||||
static const char * REPROJECTION_FS = R"FS(#version 410 core
|
||||
|
||||
uniform sampler2D sampler;
|
||||
layout (location = 0) uniform mat3 reprojection = mat3(1);
|
||||
layout (location = 4) uniform mat4 inverseProjections[2];
|
||||
layout (location = 12) uniform mat4 projections[2];
|
||||
uniform mat3 reprojection = mat3(1);
|
||||
uniform mat4 inverseProjections[2];
|
||||
uniform mat4 projections[2];
|
||||
|
||||
in vec2 vTexCoord;
|
||||
in vec3 vPosition;
|
||||
|
@ -205,6 +205,11 @@ void HmdDisplayPlugin::customizeContext() {
|
|||
_enablePreview = !isVsyncEnabled();
|
||||
_sphereSection = loadSphereSection(_program, CompositorHelper::VIRTUAL_UI_TARGET_FOV.y, CompositorHelper::VIRTUAL_UI_ASPECT_RATIO);
|
||||
compileProgram(_reprojectionProgram, REPROJECTION_VS, REPROJECTION_FS);
|
||||
|
||||
using namespace oglplus;
|
||||
REPROJECTION_MATRIX_LOCATION = Uniform<glm::mat3>(*_reprojectionProgram, "reprojection").Location();
|
||||
INVERSE_PROJECTION_MATRIX_LOCATION = Uniform<glm::mat4>(*_reprojectionProgram, "inverseProjections").Location();
|
||||
PROJECTION_MATRIX_LOCATION = Uniform<glm::mat4>(*_reprojectionProgram, "projections").Location();
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::uncustomizeContext() {
|
||||
|
|
|
@ -820,14 +820,14 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
|||
return;
|
||||
}
|
||||
|
||||
QString collisionSoundURL;
|
||||
SharedSoundPointer collisionSound;
|
||||
float mass = 1.0; // value doesn't get used, but set it so compiler is quiet
|
||||
AACube minAACube;
|
||||
bool success = false;
|
||||
_tree->withReadLock([&] {
|
||||
EntityItemPointer entity = entityTree->findEntityByEntityItemID(id);
|
||||
if (entity) {
|
||||
collisionSoundURL = entity->getCollisionSoundURL();
|
||||
collisionSound = entity->getCollisionSound();
|
||||
mass = entity->computeMass();
|
||||
minAACube = entity->getMinimumAACube(success);
|
||||
}
|
||||
|
@ -835,9 +835,10 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
|||
if (!success) {
|
||||
return;
|
||||
}
|
||||
if (collisionSoundURL.isEmpty()) {
|
||||
if (!collisionSound) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float COLLISION_PENETRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity()
|
||||
// The collision.penetration is a pretty good indicator of changed velocity AFTER the initial contact,
|
||||
// but that first contact depends on exactly where we hit in the physics step.
|
||||
|
@ -859,11 +860,10 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
|||
const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes.
|
||||
const float volume = (energyFactorOfFull * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
||||
|
||||
|
||||
// Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2)
|
||||
const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f;
|
||||
const float stretchFactor = log(1.0f + (minAACube.getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2);
|
||||
AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position);
|
||||
AudioInjector::playSound(collisionSound, volume, stretchFactor, position);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
|
||||
|
|
|
@ -51,7 +51,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
if (getFaceCamera()) {
|
||||
//rotate about vertical to face the camera
|
||||
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
|
||||
glm::vec3 dPosition = args->getViewFrustum().getPosition() - getPosition();
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
|
|
|
@ -174,9 +174,14 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
|||
#endif
|
||||
|
||||
if (!_webSurface) {
|
||||
#if defined(Q_OS_LINUX)
|
||||
// these don't seem to work on Linux
|
||||
return;
|
||||
#else
|
||||
if (!buildWebSurface(static_cast<EntityTreeRenderer*>(args->_renderer))) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
_lastRenderTime = usecTimestampNow();
|
||||
|
|
|
@ -57,8 +57,6 @@ public:
|
|||
virtual bool isMine() { return _isMine; }
|
||||
virtual void setIsMine(bool value) { _isMine = value; }
|
||||
|
||||
bool locallyAddedButNotYetReceived = false;
|
||||
|
||||
virtual bool shouldSuppressLocationEdits() { return false; }
|
||||
|
||||
virtual void prepareForPhysicsSimulation() { }
|
||||
|
|
|
@ -726,8 +726,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
{ // parentID and parentJointIndex are also protected by simulation ownership
|
||||
bool oldOverwrite = overwriteLocalData;
|
||||
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
overwriteLocalData = oldOverwrite;
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
||||
|
||||
|
@ -852,6 +857,23 @@ void EntityItem::setHref(QString value) {
|
|||
_href = value;
|
||||
}
|
||||
|
||||
void EntityItem::setCollisionSoundURL(const QString& value) {
|
||||
if (_collisionSoundURL != value) {
|
||||
_collisionSoundURL = value;
|
||||
|
||||
if (auto myTree = getTree()) {
|
||||
myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SharedSoundPointer EntityItem::getCollisionSound() {
|
||||
if (!_collisionSound) {
|
||||
_collisionSound = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
|
||||
}
|
||||
return _collisionSound;
|
||||
}
|
||||
|
||||
void EntityItem::simulate(const quint64& now) {
|
||||
if (_lastSimulated == 0) {
|
||||
_lastSimulated = now;
|
||||
|
@ -1700,16 +1722,31 @@ void EntityItem::setPendingOwnershipPriority(quint8 priority, const quint64& tim
|
|||
_simulationOwner.setPendingPriority(priority, timestamp);
|
||||
}
|
||||
|
||||
QString EntityItem::actionsToDebugString() {
|
||||
QString result;
|
||||
QVector<QByteArray> serializedActions;
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
const QUuid id = i.key();
|
||||
EntityActionPointer action = _objectActions[id];
|
||||
EntityActionType actionType = action->getType();
|
||||
result += QString("") + actionType + ":" + action->getID().toString() + " ";
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer action) {
|
||||
bool result;
|
||||
withWriteLock([&] {
|
||||
checkWaitingToRemove(simulation);
|
||||
|
||||
result = addActionInternal(simulation, action);
|
||||
if (!result) {
|
||||
removeActionInternal(action->getID());
|
||||
if (result) {
|
||||
action->setIsMine(true);
|
||||
_actionDataDirty = true;
|
||||
} else {
|
||||
action->locallyAddedButNotYetReceived = true;
|
||||
removeActionInternal(action->getID());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1783,6 +1820,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s
|
|||
EntityActionPointer action = _objectActions[actionID];
|
||||
|
||||
action->setOwnerEntity(nullptr);
|
||||
action->setIsMine(false);
|
||||
_objectActions.remove(actionID);
|
||||
|
||||
if (simulation) {
|
||||
|
@ -1863,7 +1901,6 @@ void EntityItem::deserializeActionsInternal() {
|
|||
if (!action->isMine()) {
|
||||
action->deserialize(serializedAction);
|
||||
}
|
||||
action->locallyAddedButNotYetReceived = false;
|
||||
updated << actionID;
|
||||
} else {
|
||||
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
||||
|
@ -1871,7 +1908,6 @@ void EntityItem::deserializeActionsInternal() {
|
|||
EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction);
|
||||
if (action) {
|
||||
entity->addActionInternal(simulation, action);
|
||||
action->locallyAddedButNotYetReceived = false;
|
||||
updated << actionID;
|
||||
} else {
|
||||
static QString repeatedMessage =
|
||||
|
@ -1889,8 +1925,12 @@ void EntityItem::deserializeActionsInternal() {
|
|||
QUuid id = i.key();
|
||||
if (!updated.contains(id)) {
|
||||
EntityActionPointer action = i.value();
|
||||
// if we've just added this action, don't remove it due to lack of mention in an incoming packet.
|
||||
if (! action->locallyAddedButNotYetReceived) {
|
||||
|
||||
if (action->isMine()) {
|
||||
// we just received an update that didn't include one of our actions. tell the server about it (again).
|
||||
setActionDataNeedsTransmit(true);
|
||||
} else {
|
||||
// don't let someone else delete my action.
|
||||
_actionsToRemove << id;
|
||||
_previouslyDeletedActions.insert(id, now);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <PhysicsCollisionGroups.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <Transform.h>
|
||||
#include <Sound.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
|
@ -250,7 +251,10 @@ public:
|
|||
void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
|
||||
|
||||
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
|
||||
void setCollisionSoundURL(const QString& value) { _collisionSoundURL = value; }
|
||||
void setCollisionSoundURL(const QString& value);
|
||||
|
||||
SharedSoundPointer getCollisionSound();
|
||||
void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; }
|
||||
|
||||
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
|
||||
|
||||
|
@ -378,6 +382,7 @@ public:
|
|||
void grabSimulationOwnership();
|
||||
void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }
|
||||
|
||||
QString actionsToDebugString();
|
||||
bool addAction(EntitySimulation* simulation, EntityActionPointer action);
|
||||
bool updateAction(EntitySimulation* simulation, const QUuid& actionID, const QVariantMap& arguments);
|
||||
bool removeAction(EntitySimulation* simulation, const QUuid& actionID);
|
||||
|
@ -478,6 +483,7 @@ protected:
|
|||
quint64 _loadedScriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 };
|
||||
|
||||
QString _collisionSoundURL;
|
||||
SharedSoundPointer _collisionSound;
|
||||
glm::vec3 _registrationPoint;
|
||||
float _angularDamping;
|
||||
bool _visible;
|
||||
|
|
|
@ -1615,7 +1615,7 @@ void EntityItemProperties::setSimulationOwner(const QByteArray& data) {
|
|||
QList<QString> EntityItemProperties::listChangedProperties() {
|
||||
QList<QString> out;
|
||||
if (containsPositionChange()) {
|
||||
out += "posistion";
|
||||
out += "position";
|
||||
}
|
||||
if (dimensionsChanged()) {
|
||||
out += "dimensions";
|
||||
|
|
|
@ -95,7 +95,6 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
|
|||
}
|
||||
|
||||
_isDirty = true;
|
||||
maybeNotifyNewCollisionSoundURL("", entity->getCollisionSoundURL());
|
||||
emit addingEntity(entity->getEntityItemID());
|
||||
|
||||
// find and hook up any entities with this entity as a (previously) missing parent
|
||||
|
@ -213,6 +212,8 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
properties.setVelocityChanged(false);
|
||||
properties.setAngularVelocityChanged(false);
|
||||
properties.setAccelerationChanged(false);
|
||||
properties.setParentIDChanged(false);
|
||||
properties.setParentJointIndexChanged(false);
|
||||
|
||||
if (wantTerseEditLogging()) {
|
||||
qCDebug(entities) << (senderNode ? senderNode->getUUID() : "null") << "physical edits suppressed";
|
||||
|
@ -223,7 +224,6 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
|
||||
QString entityScriptBefore = entity->getScript();
|
||||
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
|
||||
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
|
||||
uint32_t preFlags = entity->getDirtyFlags();
|
||||
|
||||
AACube newQueryAACube;
|
||||
|
@ -295,7 +295,6 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
if (entityScriptBefore != entityScriptAfter || reload) {
|
||||
emitEntityScriptChanging(entity->getEntityItemID(), reload); // the entity script has changed
|
||||
}
|
||||
maybeNotifyNewCollisionSoundURL(collisionSoundURLBefore, entity->getCollisionSoundURL());
|
||||
}
|
||||
|
||||
// TODO: this final containingElement check should eventually be removed (or wrapped in an #ifdef DEBUG).
|
||||
|
@ -362,10 +361,8 @@ void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, cons
|
|||
emit entityScriptChanging(entityItemID, reload);
|
||||
}
|
||||
|
||||
void EntityTree::maybeNotifyNewCollisionSoundURL(const QString& previousCollisionSoundURL, const QString& nextCollisionSoundURL) {
|
||||
if (!nextCollisionSoundURL.isEmpty() && (nextCollisionSoundURL != previousCollisionSoundURL)) {
|
||||
emit newCollisionSoundURL(QUrl(nextCollisionSoundURL));
|
||||
}
|
||||
void EntityTree::notifyNewCollisionSoundURL(const QString& newURL, const EntityItemID& entityID) {
|
||||
emit newCollisionSoundURL(QUrl(newURL), entityID);
|
||||
}
|
||||
|
||||
void EntityTree::setSimulation(EntitySimulation* simulation) {
|
||||
|
@ -848,6 +845,14 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
|||
QString::number((int)center.y) + "," +
|
||||
QString::number((int)center.z);
|
||||
}
|
||||
if (properties.positionChanged()) {
|
||||
int index = changedProperties.indexOf("position");
|
||||
glm::vec3 pos = properties.getPosition();
|
||||
changedProperties[index] = QString("position:") +
|
||||
QString::number((int)pos.x) + "," +
|
||||
QString::number((int)pos.y) + "," +
|
||||
QString::number((int)pos.z);
|
||||
}
|
||||
}
|
||||
|
||||
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
|
||||
|
|
|
@ -249,6 +249,8 @@ public:
|
|||
void forgetAvatarID(QUuid avatarID) { _avatarIDs -= avatarID; }
|
||||
void deleteDescendantsOfAvatar(QUuid avatarID);
|
||||
|
||||
void notifyNewCollisionSoundURL(const QString& newCollisionSoundURL, const EntityItemID& entityID);
|
||||
|
||||
public slots:
|
||||
void callLoader(EntityItemID entityID);
|
||||
|
||||
|
@ -256,7 +258,7 @@ signals:
|
|||
void deletingEntity(const EntityItemID& entityID);
|
||||
void addingEntity(const EntityItemID& entityID);
|
||||
void entityScriptChanging(const EntityItemID& entityItemID, const bool reload);
|
||||
void newCollisionSoundURL(const QUrl& url);
|
||||
void newCollisionSoundURL(const QUrl& url, const EntityItemID& entityID);
|
||||
void clearingEntities();
|
||||
|
||||
protected:
|
||||
|
@ -301,7 +303,6 @@ protected:
|
|||
|
||||
bool _wantEditLogging = false;
|
||||
bool _wantTerseEditLogging = false;
|
||||
void maybeNotifyNewCollisionSoundURL(const QString& oldCollisionSoundURL, const QString& newCollisionSoundURL);
|
||||
|
||||
|
||||
// some performance tracking properties - only used in server trees
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <FBXReader.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <OctreeUtils.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
|
@ -34,8 +35,6 @@ OctreeElementPointer EntityTreeElement::createNewElement(unsigned char* octalCod
|
|||
return newChild;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EntityTreeElement::init(unsigned char* octalCode) {
|
||||
OctreeElement::init(octalCode);
|
||||
_octreeMemoryUsage += sizeof(EntityTreeElement);
|
||||
|
@ -297,7 +296,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
|
||||
}
|
||||
|
||||
if (includeThisEntity && params.viewFrustum) {
|
||||
if (includeThisEntity || params.recurseEverything) {
|
||||
|
||||
// we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
|
||||
// simulation changing what's visible. consider the case where the entity contains an angular velocity
|
||||
|
@ -305,7 +304,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
// frustum culling on rendering.
|
||||
bool success;
|
||||
AACube entityCube = entity->getQueryAACube(success);
|
||||
if (!success || !params.viewFrustum->cubeIntersectsKeyhole(entityCube)) {
|
||||
if (!success || !params.viewFrustum.cubeIntersectsKeyhole(entityCube)) {
|
||||
includeThisEntity = false; // out of view, don't include it
|
||||
} else {
|
||||
// Check the size of the entity, it's possible that a "too small to see" entity is included in a
|
||||
|
@ -322,9 +321,10 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
// AABox. If this happens, fall back to the queryAACube.
|
||||
entityBounds = AABox(entityCube);
|
||||
}
|
||||
auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds,
|
||||
params.octreeElementSizeScale,
|
||||
params.boundaryLevelAdjust);
|
||||
auto renderAccuracy = calculateRenderAccuracy(params.viewFrustum.getPosition(),
|
||||
entityBounds,
|
||||
params.octreeElementSizeScale,
|
||||
params.boundaryLevelAdjust);
|
||||
if (renderAccuracy <= 0.0f) {
|
||||
includeThisEntity = false; // too small, don't include it
|
||||
|
||||
|
|
|
@ -17,8 +17,15 @@ QOpenGLContext* QOpenGLContextWrapper::currentContext() {
|
|||
return QOpenGLContext::currentContext();
|
||||
}
|
||||
|
||||
|
||||
QOpenGLContextWrapper::QOpenGLContextWrapper() :
|
||||
_context(new QOpenGLContext)
|
||||
_context(new QOpenGLContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QOpenGLContextWrapper::QOpenGLContextWrapper(QOpenGLContext* context) :
|
||||
_context(context)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -50,3 +57,7 @@ bool isCurrentContext(QOpenGLContext* context) {
|
|||
return QOpenGLContext::currentContext() == context;
|
||||
}
|
||||
|
||||
void QOpenGLContextWrapper::moveToThread(QThread* thread) {
|
||||
_context->moveToThread(thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,16 +15,19 @@
|
|||
class QOpenGLContext;
|
||||
class QSurface;
|
||||
class QSurfaceFormat;
|
||||
class QThread;
|
||||
|
||||
class QOpenGLContextWrapper {
|
||||
public:
|
||||
QOpenGLContextWrapper();
|
||||
QOpenGLContextWrapper(QOpenGLContext* context);
|
||||
void setFormat(const QSurfaceFormat& format);
|
||||
bool create();
|
||||
void swapBuffers(QSurface* surface);
|
||||
bool makeCurrent(QSurface* surface);
|
||||
void doneCurrent();
|
||||
void setShareContext(QOpenGLContext* otherContext);
|
||||
void moveToThread(QThread* thread);
|
||||
|
||||
static QOpenGLContext* currentContext();
|
||||
|
||||
|
|
|
@ -40,15 +40,14 @@ void ResourceCacheSharedItems::appendPendingRequest(QWeakPointer<Resource> resou
|
|||
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() {
|
||||
QList<QSharedPointer<Resource>> result;
|
||||
Lock lock(_mutex);
|
||||
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
foreach(QSharedPointer<Resource> resource, _pendingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
}
|
||||
foreach(QSharedPointer<Resource> resource, _pendingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -59,20 +58,20 @@ uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const {
|
|||
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() {
|
||||
QList<QSharedPointer<Resource>> result;
|
||||
Lock lock(_mutex);
|
||||
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
foreach(QSharedPointer<Resource> resource, _loadingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
}
|
||||
foreach(QSharedPointer<Resource> resource, _loadingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ResourceCacheSharedItems::removeRequest(QWeakPointer<Resource> resource) {
|
||||
Lock lock(_mutex);
|
||||
|
||||
// resource can only be removed if it still has a ref-count, as
|
||||
// QWeakPointer has no operator== implementation for two weak ptrs, so
|
||||
// manually loop in case resource has been freed.
|
||||
|
@ -88,11 +87,11 @@ void ResourceCacheSharedItems::removeRequest(QWeakPointer<Resource> resource) {
|
|||
}
|
||||
|
||||
QSharedPointer<Resource> ResourceCacheSharedItems::getHighestPendingRequest() {
|
||||
Lock lock(_mutex);
|
||||
// look for the highest priority pending request
|
||||
int highestIndex = -1;
|
||||
float highestPriority = -FLT_MAX;
|
||||
QSharedPointer<Resource> highestResource;
|
||||
Lock lock(_mutex);
|
||||
|
||||
for (int i = 0; i < _pendingRequests.size();) {
|
||||
// Clear any freed resources
|
||||
|
@ -139,17 +138,17 @@ void ScriptableResource::setInScript(bool isInScript) {
|
|||
}
|
||||
|
||||
void ScriptableResource::loadingChanged() {
|
||||
emit stateChanged(LOADING);
|
||||
setState(LOADING);
|
||||
}
|
||||
|
||||
void ScriptableResource::loadedChanged() {
|
||||
emit stateChanged(LOADED);
|
||||
setState(LOADED);
|
||||
}
|
||||
|
||||
void ScriptableResource::finished(bool success) {
|
||||
disconnectHelper();
|
||||
|
||||
emit stateChanged(success ? FINISHED : FAILED);
|
||||
setState(success ? FINISHED : FAILED);
|
||||
}
|
||||
|
||||
void ScriptableResource::disconnectHelper() {
|
||||
|
@ -262,12 +261,14 @@ void ResourceCache::refreshAll() {
|
|||
clearUnusedResource();
|
||||
resetResourceCounters();
|
||||
|
||||
_resourcesLock.lockForRead();
|
||||
auto resourcesCopy = _resources;
|
||||
_resourcesLock.unlock();
|
||||
QHash<QUrl, QWeakPointer<Resource>> resources;
|
||||
{
|
||||
QReadLocker locker(&_resourcesLock);
|
||||
resources = _resources;
|
||||
}
|
||||
|
||||
// Refresh all remaining resources in use
|
||||
foreach (QSharedPointer<Resource> resource, resourcesCopy) {
|
||||
foreach (QSharedPointer<Resource> resource, resources) {
|
||||
if (resource) {
|
||||
resource->refresh();
|
||||
}
|
||||
|
@ -317,17 +318,17 @@ void ResourceCache::setRequestLimit(int limit) {
|
|||
|
||||
void ResourceCache::getResourceAsynchronously(const QUrl& url) {
|
||||
qCDebug(networking) << "ResourceCache::getResourceAsynchronously" << url.toString();
|
||||
_resourcesToBeGottenLock.lockForWrite();
|
||||
QWriteLocker locker(&_resourcesToBeGottenLock);
|
||||
_resourcesToBeGotten.enqueue(QUrl(url));
|
||||
_resourcesToBeGottenLock.unlock();
|
||||
}
|
||||
|
||||
void ResourceCache::checkAsynchronousGets() {
|
||||
assert(QThread::currentThread() == thread());
|
||||
QWriteLocker locker(&_resourcesToBeGottenLock);
|
||||
if (!_resourcesToBeGotten.isEmpty()) {
|
||||
_resourcesToBeGottenLock.lockForWrite();
|
||||
QUrl url = _resourcesToBeGotten.dequeue();
|
||||
_resourcesToBeGottenLock.unlock();
|
||||
|
||||
locker.unlock();
|
||||
getResource(url);
|
||||
}
|
||||
}
|
||||
|
@ -399,8 +400,10 @@ void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resourc
|
|||
if (_unusedResources.contains(resource->getLRUKey())) {
|
||||
_unusedResources.remove(resource->getLRUKey());
|
||||
_unusedResourcesSize -= resource->getBytes();
|
||||
|
||||
locker.unlock();
|
||||
resetResourceCounters();
|
||||
}
|
||||
resetResourceCounters();
|
||||
}
|
||||
|
||||
void ResourceCache::reserveUnusedResource(qint64 resourceSize) {
|
||||
|
@ -413,7 +416,9 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) {
|
|||
it.value()->setCache(nullptr);
|
||||
auto size = it.value()->getBytes();
|
||||
|
||||
locker.unlock();
|
||||
removeResource(it.value()->getURL(), size);
|
||||
locker.relock();
|
||||
|
||||
_unusedResourcesSize -= size;
|
||||
_unusedResources.erase(it);
|
||||
|
@ -433,8 +438,16 @@ void ResourceCache::clearUnusedResource() {
|
|||
}
|
||||
|
||||
void ResourceCache::resetResourceCounters() {
|
||||
_numTotalResources = _resources.size();
|
||||
_numUnusedResources = _unusedResources.size();
|
||||
{
|
||||
QReadLocker locker(&_resourcesLock);
|
||||
_numTotalResources = _resources.size();
|
||||
}
|
||||
|
||||
{
|
||||
QReadLocker locker(&_unusedResourcesLock);
|
||||
_numUnusedResources = _unusedResources.size();
|
||||
}
|
||||
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ class ResourceCacheSharedItems : public Dependency {
|
|||
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
|
||||
public:
|
||||
void appendPendingRequest(QWeakPointer<Resource> newRequest);
|
||||
void appendActiveRequest(QWeakPointer<Resource> newRequest);
|
||||
|
@ -113,6 +114,9 @@ signals:
|
|||
void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal);
|
||||
void stateChanged(int state);
|
||||
|
||||
protected:
|
||||
void setState(State state) { _state = state; emit stateChanged(_state); }
|
||||
|
||||
private slots:
|
||||
void loadingChanged();
|
||||
void loadedChanged();
|
||||
|
@ -224,26 +228,30 @@ private:
|
|||
void resetResourceCounters();
|
||||
void removeResource(const QUrl& url, qint64 size = 0);
|
||||
|
||||
QReadWriteLock _resourcesLock { QReadWriteLock::Recursive };
|
||||
QHash<QUrl, QWeakPointer<Resource>> _resources;
|
||||
int _lastLRUKey = 0;
|
||||
|
||||
void getResourceAsynchronously(const QUrl& url);
|
||||
|
||||
static int _requestLimit;
|
||||
static int _requestsActive;
|
||||
|
||||
void getResourceAsynchronously(const QUrl& url);
|
||||
QReadWriteLock _resourcesToBeGottenLock { QReadWriteLock::Recursive };
|
||||
QQueue<QUrl> _resourcesToBeGotten;
|
||||
|
||||
std::atomic<size_t> _numTotalResources { 0 };
|
||||
std::atomic<size_t> _numUnusedResources { 0 };
|
||||
// Resources
|
||||
QHash<QUrl, QWeakPointer<Resource>> _resources;
|
||||
QReadWriteLock _resourcesLock { QReadWriteLock::Recursive };
|
||||
int _lastLRUKey = 0;
|
||||
|
||||
std::atomic<size_t> _numTotalResources { 0 };
|
||||
std::atomic<qint64> _totalResourcesSize { 0 };
|
||||
|
||||
// Cached resources
|
||||
QMap<int, QSharedPointer<Resource>> _unusedResources;
|
||||
QReadWriteLock _unusedResourcesLock { QReadWriteLock::Recursive };
|
||||
qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
|
||||
|
||||
std::atomic<size_t> _numUnusedResources { 0 };
|
||||
std::atomic<qint64> _unusedResourcesSize { 0 };
|
||||
|
||||
qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
|
||||
QReadWriteLock _unusedResourcesLock { QReadWriteLock::Recursive };
|
||||
QMap<int, QSharedPointer<Resource>> _unusedResources;
|
||||
// Pending resources
|
||||
QQueue<QUrl> _resourcesToBeGotten;
|
||||
QReadWriteLock _resourcesToBeGottenLock { QReadWriteLock::Recursive };
|
||||
};
|
||||
|
||||
/// Base class for resources.
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QString>
|
||||
|
||||
#include <GeometryUtil.h>
|
||||
#include <Gzip.h>
|
||||
#include <LogHandler.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <OctalCode.h>
|
||||
|
@ -40,12 +41,12 @@
|
|||
#include <ResourceManager.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <PathUtils.h>
|
||||
#include <Gzip.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "OctreeConstants.h"
|
||||
#include "OctreeElementBag.h"
|
||||
#include "Octree.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "OctreeUtils.h"
|
||||
#include "OctreeLogging.h"
|
||||
|
||||
|
||||
|
@ -898,7 +899,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element,
|
|||
}
|
||||
|
||||
// If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
|
||||
if (params.viewFrustum && !element->isInView(*params.viewFrustum)) {
|
||||
if (!params.recurseEverything && !element->isInView(params.viewFrustum)) {
|
||||
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
|
||||
return bytesWritten;
|
||||
}
|
||||
|
@ -1014,15 +1015,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
}
|
||||
|
||||
ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside
|
||||
|
||||
// caller can pass NULL as viewFrustum if they want everything
|
||||
if (params.viewFrustum) {
|
||||
float distance = element->distanceToCamera(*params.viewFrustum);
|
||||
if (!params.recurseEverything) {
|
||||
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
|
||||
params.octreeElementSizeScale);
|
||||
|
||||
// If we're too far away for our render level, then just return
|
||||
if (distance >= boundaryDistance) {
|
||||
if (element->distanceToCamera(params.viewFrustum) >= boundaryDistance) {
|
||||
if (params.stats) {
|
||||
params.stats->skippedDistance(element);
|
||||
}
|
||||
|
@ -1034,7 +1032,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
// if we are INSIDE, INTERSECT, or OUTSIDE
|
||||
if (parentLocationThisView != ViewFrustum::INSIDE) {
|
||||
assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE!
|
||||
nodeLocationThisView = element->computeViewIntersection(*params.viewFrustum);
|
||||
nodeLocationThisView = element->computeViewIntersection(params.viewFrustum);
|
||||
}
|
||||
|
||||
// If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
|
||||
|
@ -1052,8 +1050,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
// because we don't send nodes from the previously know in view frustum.
|
||||
bool wasInView = false;
|
||||
|
||||
if (params.deltaViewFrustum && params.lastViewFrustum) {
|
||||
ViewFrustum::intersection location = element->computeViewIntersection(*params.lastViewFrustum);
|
||||
if (params.deltaView) {
|
||||
ViewFrustum::intersection location = element->computeViewIntersection(params.lastViewFrustum);
|
||||
|
||||
// If we're a leaf, then either intersect or inside is considered "formerly in view"
|
||||
if (element->isLeaf()) {
|
||||
|
@ -1067,10 +1065,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
// to it, and so therefore it may now be visible from an LOD perspective, in which case we don't consider it
|
||||
// as "was in view"...
|
||||
if (wasInView) {
|
||||
float distance = element->distanceToCamera(*params.lastViewFrustum);
|
||||
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
|
||||
params.octreeElementSizeScale);
|
||||
if (distance >= boundaryDistance) {
|
||||
if (element->distanceToCamera(params.lastViewFrustum) >= boundaryDistance) {
|
||||
// This would have been invisible... but now should be visible (we wouldn't be here otherwise)...
|
||||
wasInView = false;
|
||||
}
|
||||
|
@ -1078,9 +1075,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
}
|
||||
|
||||
// If we were previously in the view, then we normally will return out of here and stop recursing. But
|
||||
// if we're in deltaViewFrustum mode, and this element has changed since it was last sent, then we do
|
||||
// if we're in deltaView mode, and this element has changed since it was last sent, then we do
|
||||
// need to send it.
|
||||
if (wasInView && !(params.deltaViewFrustum && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
|
||||
if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
|
||||
if (params.stats) {
|
||||
params.stats->skippedWasInView(element);
|
||||
}
|
||||
|
@ -1090,7 +1087,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
|
||||
// If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
|
||||
// then we can also bail early and save bits
|
||||
if (!params.forceSendScene && !params.deltaViewFrustum &&
|
||||
if (!params.forceSendScene && !params.deltaView &&
|
||||
!element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
|
||||
if (params.stats) {
|
||||
params.stats->skippedNoChange(element);
|
||||
|
@ -1179,10 +1176,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
int originalIndex = indexOfChildren[i];
|
||||
|
||||
bool childIsInView = (childElement &&
|
||||
( !params.viewFrustum || // no view frustum was given, everything is assumed in view
|
||||
(nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
|
||||
(params.recurseEverything ||
|
||||
(nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
|
||||
(nodeLocationThisView == ViewFrustum::INTERSECT &&
|
||||
childElement->isInView(*params.viewFrustum)) // the parent intersects and the child is in view
|
||||
childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view
|
||||
));
|
||||
|
||||
if (!childIsInView) {
|
||||
|
@ -1192,12 +1189,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
}
|
||||
} else {
|
||||
// Before we consider this further, let's see if it's in our LOD scope...
|
||||
float distance = distancesToChildren[i];
|
||||
float boundaryDistance = !params.viewFrustum ? 1 :
|
||||
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
|
||||
float boundaryDistance = params.recurseEverything ? 1 :
|
||||
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
|
||||
params.octreeElementSizeScale);
|
||||
|
||||
if (!(distance < boundaryDistance)) {
|
||||
if (!(distancesToChildren[i] < boundaryDistance)) {
|
||||
// don't need to check childElement here, because we can't get here with no childElement
|
||||
if (params.stats) {
|
||||
params.stats->skippedDistance(childElement);
|
||||
|
@ -1215,10 +1211,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
|
||||
bool childIsOccluded = false; // assume it's not occluded
|
||||
|
||||
bool shouldRender = !params.viewFrustum
|
||||
? true
|
||||
: childElement->calculateShouldRender(params.viewFrustum,
|
||||
params.octreeElementSizeScale, params.boundaryLevelAdjust);
|
||||
bool shouldRender = params.recurseEverything ||
|
||||
childElement->calculateShouldRender(params.viewFrustum,
|
||||
params.octreeElementSizeScale, params.boundaryLevelAdjust);
|
||||
|
||||
// track some stats
|
||||
if (params.stats) {
|
||||
|
@ -1236,8 +1231,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
if (shouldRender && !childIsOccluded) {
|
||||
bool childWasInView = false;
|
||||
|
||||
if (childElement && params.deltaViewFrustum && params.lastViewFrustum) {
|
||||
ViewFrustum::intersection location = childElement->computeViewIntersection(*params.lastViewFrustum);
|
||||
if (childElement && params.deltaView) {
|
||||
ViewFrustum::intersection location = childElement->computeViewIntersection(params.lastViewFrustum);
|
||||
|
||||
// If we're a leaf, then either intersect or inside is considered "formerly in view"
|
||||
if (childElement->isLeaf()) {
|
||||
|
@ -1251,7 +1246,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
// Or if we were previously in the view, but this element has changed since it was last sent, then we do
|
||||
// need to send it.
|
||||
if (!childWasInView ||
|
||||
(params.deltaViewFrustum &&
|
||||
(params.deltaView &&
|
||||
childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
|
||||
|
||||
childrenDataBits += (1 << (7 - originalIndex));
|
||||
|
@ -1456,7 +1451,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
|
|||
// called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep
|
||||
// recursing, by returning TRUE in recurseChildrenWithData().
|
||||
|
||||
if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) {
|
||||
if (params.recurseEverything || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) {
|
||||
|
||||
// Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this
|
||||
// will be true. But if the tree has already been encoded, we will skip this.
|
||||
|
@ -1978,7 +1973,8 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElementPointer element)
|
|||
bool lastPacketWritten = false;
|
||||
|
||||
while (OctreeElementPointer subTree = elementBag.extract()) {
|
||||
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, NO_EXISTS_BITS);
|
||||
EncodeBitstreamParams params(INT_MAX, NO_EXISTS_BITS);
|
||||
params.recurseEverything = true;
|
||||
withReadLock([&] {
|
||||
params.extraEncodeData = &extraEncodeData;
|
||||
bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "JurisdictionMap.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "OctreeElement.h"
|
||||
#include "OctreeElementBag.h"
|
||||
#include "OctreePacketData.h"
|
||||
|
@ -61,22 +61,22 @@ const int LOW_RES_MOVING_ADJUST = 1;
|
|||
const quint64 IGNORE_LAST_SENT = 0;
|
||||
|
||||
#define IGNORE_SCENE_STATS NULL
|
||||
#define IGNORE_VIEW_FRUSTUM NULL
|
||||
#define IGNORE_COVERAGE_MAP NULL
|
||||
#define IGNORE_JURISDICTION_MAP NULL
|
||||
|
||||
class EncodeBitstreamParams {
|
||||
public:
|
||||
ViewFrustum viewFrustum;
|
||||
ViewFrustum lastViewFrustum;
|
||||
quint64 lastViewFrustumSent;
|
||||
int maxEncodeLevel;
|
||||
int maxLevelReached;
|
||||
const ViewFrustum* viewFrustum;
|
||||
bool includeExistsBits;
|
||||
int chopLevels;
|
||||
bool deltaViewFrustum;
|
||||
const ViewFrustum* lastViewFrustum;
|
||||
bool deltaView;
|
||||
bool recurseEverything { false };
|
||||
int boundaryLevelAdjust;
|
||||
float octreeElementSizeScale;
|
||||
quint64 lastViewFrustumSent;
|
||||
bool forceSendScene;
|
||||
OctreeSceneStats* stats;
|
||||
JurisdictionMap* jurisdictionMap;
|
||||
|
@ -99,11 +99,9 @@ public:
|
|||
|
||||
EncodeBitstreamParams(
|
||||
int maxEncodeLevel = INT_MAX,
|
||||
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
bool includeExistsBits = WANT_EXISTS_BITS,
|
||||
int chopLevels = 0,
|
||||
bool deltaViewFrustum = false,
|
||||
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
bool useDeltaView = false,
|
||||
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
|
||||
float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
|
||||
quint64 lastViewFrustumSent = IGNORE_LAST_SENT,
|
||||
|
@ -111,22 +109,22 @@ public:
|
|||
OctreeSceneStats* stats = IGNORE_SCENE_STATS,
|
||||
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP,
|
||||
OctreeElementExtraEncodeData* extraEncodeData = NULL) :
|
||||
lastViewFrustumSent(lastViewFrustumSent),
|
||||
maxEncodeLevel(maxEncodeLevel),
|
||||
maxLevelReached(0),
|
||||
viewFrustum(viewFrustum),
|
||||
includeExistsBits(includeExistsBits),
|
||||
chopLevels(chopLevels),
|
||||
deltaViewFrustum(deltaViewFrustum),
|
||||
lastViewFrustum(lastViewFrustum),
|
||||
deltaView(useDeltaView),
|
||||
boundaryLevelAdjust(boundaryLevelAdjust),
|
||||
octreeElementSizeScale(octreeElementSizeScale),
|
||||
lastViewFrustumSent(lastViewFrustumSent),
|
||||
forceSendScene(forceSendScene),
|
||||
stats(stats),
|
||||
jurisdictionMap(jurisdictionMap),
|
||||
extraEncodeData(extraEncodeData),
|
||||
stopReason(UNKNOWN)
|
||||
{}
|
||||
{
|
||||
lastViewFrustum.invalidate();
|
||||
}
|
||||
|
||||
void displayStopReason() {
|
||||
printf("StopReason: ");
|
||||
|
@ -341,7 +339,7 @@ public:
|
|||
|
||||
bool getIsClient() const { return !_isServer; } /// Is this a client based tree. Allows guards for certain operations
|
||||
void setIsClient(bool isClient) { _isServer = !isClient; }
|
||||
|
||||
|
||||
virtual void dumpTree() { }
|
||||
virtual void pruneTree() { }
|
||||
|
||||
|
@ -352,7 +350,6 @@ public:
|
|||
virtual quint64 getAverageCreateTime() const { return 0; }
|
||||
virtual quint64 getAverageLoggingTime() const { return 0; }
|
||||
|
||||
|
||||
signals:
|
||||
void importSize(float x, float y, float z);
|
||||
void importProgress(int progress);
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
|
||||
#include "AACube.h"
|
||||
#include "OctalCode.h"
|
||||
#include "Octree.h"
|
||||
#include "OctreeConstants.h"
|
||||
#include "OctreeElement.h"
|
||||
#include "Octree.h"
|
||||
#include "OctreeLogging.h"
|
||||
#include "OctreeUtils.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 };
|
||||
|
@ -471,11 +472,11 @@ ViewFrustum::intersection OctreeElement::computeViewIntersection(const ViewFrust
|
|||
// Since, if we know the camera position and orientation, we can know which of the corners is the "furthest"
|
||||
// corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of.
|
||||
// By doing this, we don't need to test each child voxel's position vs the LOD boundary
|
||||
bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
|
||||
bool OctreeElement::calculateShouldRender(const ViewFrustum& viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
|
||||
bool shouldRender = false;
|
||||
|
||||
if (hasContent()) {
|
||||
float furthestDistance = furthestDistanceToCamera(*viewFrustum);
|
||||
float furthestDistance = furthestDistanceToCamera(viewFrustum);
|
||||
float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize);
|
||||
bool inChildBoundary = (furthestDistance <= childBoundary);
|
||||
if (hasDetailedContent() && inChildBoundary) {
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
#include <OctalCode.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "AACube.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
using AtomicUIntStat = std::atomic<uintmax_t>;
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
float distanceToCamera(const ViewFrustum& viewFrustum) const;
|
||||
float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
|
||||
|
||||
bool calculateShouldRender(const ViewFrustum* viewFrustum,
|
||||
bool calculateShouldRender(const ViewFrustum& viewFrustum,
|
||||
float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
|
||||
|
||||
// points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
|
||||
|
|
|
@ -14,14 +14,12 @@
|
|||
#include "OctreeLogging.h"
|
||||
#include "OctreeHeadlessViewer.h"
|
||||
|
||||
OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer()
|
||||
{
|
||||
OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer() {
|
||||
_viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
|
||||
}
|
||||
|
||||
void OctreeHeadlessViewer::init() {
|
||||
OctreeRenderer::init();
|
||||
setViewFrustum(&_viewFrustum);
|
||||
}
|
||||
|
||||
void OctreeHeadlessViewer::queryOctree() {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "JurisdictionListener.h"
|
||||
#include "Octree.h"
|
||||
|
@ -22,7 +23,6 @@
|
|||
#include "OctreeRenderer.h"
|
||||
#include "OctreeSceneStats.h"
|
||||
#include "Octree.h"
|
||||
#include "ViewFrustum.h"
|
||||
|
||||
// Generic client side Octree renderer class.
|
||||
class OctreeHeadlessViewer : public OctreeRenderer {
|
||||
|
@ -66,7 +66,6 @@ public slots:
|
|||
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
|
||||
|
||||
private:
|
||||
ViewFrustum _viewFrustum;
|
||||
JurisdictionListener* _jurisdictionListener = nullptr;
|
||||
OctreeQuery _octreeQuery;
|
||||
|
||||
|
|
|
@ -120,4 +120,3 @@ glm::vec3 OctreeQuery::calculateCameraDirection() const {
|
|||
glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f));
|
||||
return direction;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
|
||||
OctreeRenderer::OctreeRenderer() :
|
||||
_tree(NULL),
|
||||
_managedTree(false),
|
||||
_viewFrustum(NULL)
|
||||
_managedTree(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -201,9 +200,9 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer
|
|||
|
||||
bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) {
|
||||
RenderArgs* args = static_cast<RenderArgs*>(extraData);
|
||||
if (element->isInView(*args->_viewFrustum)) {
|
||||
if (element->isInView(args->getViewFrustum())) {
|
||||
if (element->hasContent()) {
|
||||
if (element->calculateShouldRender(args->_viewFrustum, args->_sizeScale, args->_boundaryLevelAdjust)) {
|
||||
if (element->calculateShouldRender(args->getViewFrustum(), args->_sizeScale, args->_boundaryLevelAdjust)) {
|
||||
args->_renderer->renderElement(element, args);
|
||||
} else {
|
||||
return false; // if we shouldn't render, then we also should stop recursing.
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#include <udt/PacketHeaders.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "Octree.h"
|
||||
#include "OctreePacketData.h"
|
||||
#include "ViewFrustum.h"
|
||||
|
||||
class OctreeRenderer;
|
||||
|
||||
|
@ -51,8 +51,8 @@ public:
|
|||
/// render the content of the octree
|
||||
virtual void render(RenderArgs* renderArgs);
|
||||
|
||||
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||
const ViewFrustum& getViewFrustum() const { return _viewFrustum; }
|
||||
void setViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustum = viewFrustum; }
|
||||
|
||||
static bool renderOperation(OctreeElementPointer element, void* extraData);
|
||||
|
||||
|
@ -75,7 +75,7 @@ protected:
|
|||
|
||||
OctreePointer _tree;
|
||||
bool _managedTree;
|
||||
ViewFrustum* _viewFrustum;
|
||||
ViewFrustum _viewFrustum;
|
||||
|
||||
SimpleMovingAverage _elementsPerPacket;
|
||||
SimpleMovingAverage _entitiesPerPacket;
|
||||
|
|
71
libraries/octree/src/OctreeUtils.cpp
Normal file
71
libraries/octree/src/OctreeUtils.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// OctreeUtils.cpp
|
||||
// libraries/octree/src
|
||||
//
|
||||
// Created by Andrew Meadows 2016.03.04
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OctreeUtils.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <AABox.h>
|
||||
|
||||
|
||||
float calculateRenderAccuracy(const glm::vec3& position,
|
||||
const AABox& bounds,
|
||||
float octreeSizeScale,
|
||||
int boundaryLevelAdjust) {
|
||||
float largestDimension = bounds.getLargestDimension();
|
||||
|
||||
const float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
||||
|
||||
static std::once_flag once;
|
||||
static QMap<float, float> shouldRenderTable;
|
||||
std::call_once(once, [&] {
|
||||
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
|
||||
float scale = maxScale;
|
||||
float factor = 1.0f;
|
||||
|
||||
while (scale > SMALLEST_SCALE_IN_TABLE) {
|
||||
scale /= 2.0f;
|
||||
factor /= 2.0f;
|
||||
shouldRenderTable[scale] = factor;
|
||||
}
|
||||
});
|
||||
|
||||
float closestScale = maxScale;
|
||||
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
|
||||
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
|
||||
if (lowerBound != shouldRenderTable.constEnd()) {
|
||||
closestScale = lowerBound.key();
|
||||
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
|
||||
}
|
||||
|
||||
if (closestScale < largestDimension) {
|
||||
visibleDistanceAtClosestScale *= 2.0f;
|
||||
}
|
||||
|
||||
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
|
||||
// a floating point for objects that have small angular size to indicate that they may be rendered
|
||||
// with lower preciscion
|
||||
float distanceToCamera = glm::length(bounds.calcCenter() - position);
|
||||
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
||||
return voxelSizeScale / powf(2.0f, renderLevel);
|
||||
}
|
||||
|
||||
float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) {
|
||||
const float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
||||
return atan(maxScale / visibleDistanceAtMaxScale);
|
||||
}
|
30
libraries/octree/src/OctreeUtils.h
Normal file
30
libraries/octree/src/OctreeUtils.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// OctreeUtils.h
|
||||
// libraries/octree/src
|
||||
//
|
||||
// Created by Andrew Meadows 2016.03.04
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_OctreeUtils_h
|
||||
#define hifi_OctreeUtils_h
|
||||
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
class AABox;
|
||||
|
||||
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
|
||||
/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
|
||||
float calculateRenderAccuracy(const glm::vec3& position,
|
||||
const AABox& bounds,
|
||||
float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
|
||||
int boundaryLevelAdjust = 0);
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
||||
|
||||
float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust);
|
||||
|
||||
#endif // hifi_OctreeUtils_h
|
|
@ -430,6 +430,14 @@ glm::vec3 CharacterController::getLinearVelocity() const {
|
|||
return velocity;
|
||||
}
|
||||
|
||||
glm::vec3 CharacterController::getVelocityChange() const {
|
||||
glm::vec3 velocity(0.0f);
|
||||
if (_rigidBody) {
|
||||
velocity = bulletToGLM(_rigidBody->getLinearVelocity());
|
||||
}
|
||||
return velocity;
|
||||
}
|
||||
|
||||
void CharacterController::preSimulation() {
|
||||
if (_enabled && _dynamicsWorld) {
|
||||
quint64 now = usecTimestampNow();
|
||||
|
@ -437,6 +445,7 @@ void CharacterController::preSimulation() {
|
|||
// slam body to where it is supposed to be
|
||||
_rigidBody->setWorldTransform(_characterBodyTransform);
|
||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
||||
_preSimulationVelocity = velocity;
|
||||
|
||||
btVector3 actualVertVelocity = velocity.dot(_currentUp) * _currentUp;
|
||||
btVector3 actualHorizVelocity = velocity - actualVertVelocity;
|
||||
|
@ -531,6 +540,9 @@ void CharacterController::preSimulation() {
|
|||
|
||||
void CharacterController::postSimulation() {
|
||||
// postSimulation() exists for symmetry and just in case we need to do something here later
|
||||
|
||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
||||
_velocityChange = velocity - _preSimulationVelocity;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
glm::vec3 getFollowVelocity() const;
|
||||
|
||||
glm::vec3 getLinearVelocity() const;
|
||||
glm::vec3 getVelocityChange() const;
|
||||
|
||||
float getCapsuleRadius() const { return _radius; }
|
||||
float getCapsuleHalfHeight() const { return _halfHeight; }
|
||||
|
@ -112,6 +113,8 @@ protected:
|
|||
btVector3 _currentUp;
|
||||
btVector3 _targetVelocity;
|
||||
btVector3 _parentVelocity;
|
||||
btVector3 _preSimulationVelocity;
|
||||
btVector3 _velocityChange;
|
||||
btTransform _followDesiredBodyTransform;
|
||||
btScalar _followTimeRemaining;
|
||||
btTransform _characterBodyTransform;
|
||||
|
|
|
@ -21,9 +21,11 @@ const uint16_t ObjectActionSpring::springVersion = 1;
|
|||
ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(ACTION_TYPE_SPRING, id, ownerEntity),
|
||||
_positionalTarget(glm::vec3(0.0f)),
|
||||
_desiredPositionalTarget(glm::vec3(0.0f)),
|
||||
_linearTimeScale(FLT_MAX),
|
||||
_positionalTargetSet(true),
|
||||
_rotationalTarget(glm::quat()),
|
||||
_desiredRotationalTarget(glm::quat()),
|
||||
_angularTimeScale(FLT_MAX),
|
||||
_rotationalTargetSet(true) {
|
||||
#if WANT_DEBUG
|
||||
|
@ -37,9 +39,81 @@ ObjectActionSpring::~ObjectActionSpring() {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool ObjectActionSpring::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity) {
|
||||
rotation = _desiredRotationalTarget;
|
||||
position = _desiredPositionalTarget;
|
||||
linearVelocity = glm::vec3();
|
||||
angularVelocity = glm::vec3();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) {
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::quat rotation;
|
||||
glm::vec3 position;
|
||||
glm::vec3 linearVelocity;
|
||||
glm::vec3 angularVelocity;
|
||||
|
||||
bool valid = false;
|
||||
int springCount = 0;
|
||||
|
||||
QList<EntityActionPointer> springDerivedActions;
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_SPRING));
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_HOLD));
|
||||
|
||||
foreach (EntityActionPointer action, springDerivedActions) {
|
||||
std::shared_ptr<ObjectActionSpring> springAction = std::static_pointer_cast<ObjectActionSpring>(action);
|
||||
glm::quat rotationForAction;
|
||||
glm::vec3 positionForAction;
|
||||
glm::vec3 linearVelocityForAction, angularVelocityForAction;
|
||||
bool success = springAction->getTarget(deltaTimeStep, rotationForAction,
|
||||
positionForAction, linearVelocityForAction,
|
||||
angularVelocityForAction);
|
||||
if (success) {
|
||||
springCount ++;
|
||||
if (springAction.get() == this) {
|
||||
// only use the rotation for this action
|
||||
valid = true;
|
||||
rotation = rotationForAction;
|
||||
}
|
||||
|
||||
position += positionForAction;
|
||||
linearVelocity += linearVelocityForAction;
|
||||
angularVelocity += angularVelocityForAction;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid && springCount > 0) {
|
||||
position /= springCount;
|
||||
linearVelocity /= springCount;
|
||||
angularVelocity /= springCount;
|
||||
|
||||
withWriteLock([&]{
|
||||
_positionalTarget = position;
|
||||
_rotationalTarget = rotation;
|
||||
_linearVelocityTarget = linearVelocity;
|
||||
_angularVelocityTarget = angularVelocity;
|
||||
_positionalTargetSet = true;
|
||||
_rotationalTargetSet = true;
|
||||
_active = true;
|
||||
});
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
||||
// don't risk hanging the thread running the physics simulation
|
||||
auto lockResult = withTryReadLock([&]{
|
||||
if (!prepareForSpringUpdate(deltaTimeStep)) {
|
||||
return;
|
||||
}
|
||||
|
||||
withReadLock([&]{
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
|
@ -65,6 +139,7 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|||
float speed = glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED);
|
||||
targetVelocity = (-speed / offsetLength) * offset;
|
||||
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
||||
forceBodyNonStatic();
|
||||
rigidBody->activate();
|
||||
}
|
||||
}
|
||||
|
@ -101,9 +176,6 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|||
rigidBody->setAngularVelocity(targetVelocity);
|
||||
}
|
||||
});
|
||||
if (!lockResult) {
|
||||
qDebug() << "ObjectActionSpring::updateActionWorker lock failed";
|
||||
}
|
||||
}
|
||||
|
||||
const float MIN_TIMESCALE = 0.1f;
|
||||
|
@ -122,7 +194,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
bool ok = true;
|
||||
positionalTarget = EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
|
||||
if (!ok) {
|
||||
positionalTarget = _positionalTarget;
|
||||
positionalTarget = _desiredPositionalTarget;
|
||||
}
|
||||
ok = true;
|
||||
linearTimeScale = EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
|
||||
|
@ -133,7 +205,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
ok = true;
|
||||
rotationalTarget = EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
|
||||
if (!ok) {
|
||||
rotationalTarget = _rotationalTarget;
|
||||
rotationalTarget = _desiredRotationalTarget;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
|
@ -144,9 +216,9 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
}
|
||||
|
||||
if (somethingChanged ||
|
||||
positionalTarget != _positionalTarget ||
|
||||
positionalTarget != _desiredPositionalTarget ||
|
||||
linearTimeScale != _linearTimeScale ||
|
||||
rotationalTarget != _rotationalTarget ||
|
||||
rotationalTarget != _desiredRotationalTarget ||
|
||||
angularTimeScale != _angularTimeScale) {
|
||||
// something changed
|
||||
needUpdate = true;
|
||||
|
@ -155,9 +227,9 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
|
||||
if (needUpdate) {
|
||||
withWriteLock([&] {
|
||||
_positionalTarget = positionalTarget;
|
||||
_desiredPositionalTarget = positionalTarget;
|
||||
_linearTimeScale = glm::max(MIN_TIMESCALE, glm::abs(linearTimeScale));
|
||||
_rotationalTarget = rotationalTarget;
|
||||
_desiredRotationalTarget = rotationalTarget;
|
||||
_angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale));
|
||||
_active = true;
|
||||
|
||||
|
@ -177,9 +249,9 @@ QVariantMap ObjectActionSpring::getArguments() {
|
|||
QVariantMap arguments = ObjectAction::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["linearTimeScale"] = _linearTimeScale;
|
||||
arguments["targetPosition"] = glmToQMap(_positionalTarget);
|
||||
arguments["targetPosition"] = glmToQMap(_desiredPositionalTarget);
|
||||
|
||||
arguments["targetRotation"] = glmToQMap(_rotationalTarget);
|
||||
arguments["targetRotation"] = glmToQMap(_desiredRotationalTarget);
|
||||
arguments["angularTimeScale"] = _angularTimeScale;
|
||||
});
|
||||
return arguments;
|
||||
|
@ -194,10 +266,10 @@ QByteArray ObjectActionSpring::serialize() const {
|
|||
dataStream << ObjectActionSpring::springVersion;
|
||||
|
||||
withReadLock([&] {
|
||||
dataStream << _positionalTarget;
|
||||
dataStream << _desiredPositionalTarget;
|
||||
dataStream << _linearTimeScale;
|
||||
dataStream << _positionalTargetSet;
|
||||
dataStream << _rotationalTarget;
|
||||
dataStream << _desiredRotationalTarget;
|
||||
dataStream << _angularTimeScale;
|
||||
dataStream << _rotationalTargetSet;
|
||||
dataStream << localTimeToServerTime(_expires);
|
||||
|
@ -226,11 +298,11 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
|
|||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
dataStream >> _positionalTarget;
|
||||
dataStream >> _desiredPositionalTarget;
|
||||
dataStream >> _linearTimeScale;
|
||||
dataStream >> _positionalTargetSet;
|
||||
|
||||
dataStream >> _rotationalTarget;
|
||||
dataStream >> _desiredRotationalTarget;
|
||||
dataStream >> _angularTimeScale;
|
||||
dataStream >> _rotationalTargetSet;
|
||||
|
||||
|
|
|
@ -27,16 +27,26 @@ public:
|
|||
virtual QByteArray serialize() const override;
|
||||
virtual void deserialize(QByteArray serializedArguments) override;
|
||||
|
||||
virtual bool getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity);
|
||||
|
||||
protected:
|
||||
static const uint16_t springVersion;
|
||||
|
||||
glm::vec3 _positionalTarget;
|
||||
glm::vec3 _desiredPositionalTarget;
|
||||
float _linearTimeScale;
|
||||
bool _positionalTargetSet;
|
||||
|
||||
glm::quat _rotationalTarget;
|
||||
glm::quat _desiredRotationalTarget;
|
||||
float _angularTimeScale;
|
||||
bool _rotationalTargetSet;
|
||||
|
||||
glm::vec3 _linearVelocityTarget;
|
||||
glm::vec3 _angularVelocityTarget;
|
||||
|
||||
virtual bool prepareForSpringUpdate(btScalar deltaTimeStep);
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectActionSpring_h
|
||||
|
|
|
@ -32,7 +32,11 @@ const LoaderList& getLoadedPlugins() {
|
|||
static std::once_flag once;
|
||||
static LoaderList loadedPlugins;
|
||||
std::call_once(once, [&] {
|
||||
#ifdef Q_OS_MAC
|
||||
QString pluginPath = QCoreApplication::applicationDirPath() + "/../PlugIns/";
|
||||
#else
|
||||
QString pluginPath = QCoreApplication::applicationDirPath() + "/plugins/";
|
||||
#endif
|
||||
QDir pluginDir(pluginPath);
|
||||
pluginDir.setFilter(QDir::Files);
|
||||
if (pluginDir.exists()) {
|
||||
|
|
|
@ -28,14 +28,14 @@ class PickRay;
|
|||
/// Interface provided by Application to other objects that need access to the current view state details
|
||||
class AbstractViewStateInterface {
|
||||
public:
|
||||
/// gets the current view frustum for rendering the view state
|
||||
virtual ViewFrustum* getCurrentViewFrustum() = 0;
|
||||
/// copies the current view frustum for rendering the view state
|
||||
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
|
||||
|
||||
/// gets the shadow view frustum for rendering the view state
|
||||
virtual ViewFrustum* getShadowViewFrustum() = 0;
|
||||
/// copies the shadow view frustum for rendering the view state
|
||||
virtual void copyShadowViewFrustum(ViewFrustum& viewOut) const = 0;
|
||||
|
||||
virtual QThread* getMainThread() = 0;
|
||||
|
||||
|
||||
virtual PickRay computePickRay(float x, float y) const = 0;
|
||||
|
||||
virtual glm::vec3 getAvatarPosition() const = 0;
|
||||
|
|
|
@ -284,7 +284,7 @@ void AmbientOcclusionEffect::updateGaussianDistribution() {
|
|||
|
||||
void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
|
@ -309,7 +309,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
|
|||
auto resolutionLevel = getResolutionLevel();
|
||||
|
||||
// Update the depth info with near and far (same for stereo)
|
||||
setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
|
||||
setDepthInfo(args->getViewFrustum().getNearClip(), args->getViewFrustum().getFarClip());
|
||||
|
||||
_frameTransformBuffer.edit<FrameTransform>().pixelInfo = args->_viewport;
|
||||
//_parametersBuffer.edit<Parameters>()._ditheringInfo.y += 0.25f;
|
||||
|
@ -319,7 +319,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
|
|||
if (!isStereo) {
|
||||
// Eval the mono projection
|
||||
mat4 monoProjMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(monoProjMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(monoProjMat);
|
||||
_frameTransformBuffer.edit<FrameTransform>().projection[0] = monoProjMat;
|
||||
_frameTransformBuffer.edit<FrameTransform>().stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
|
||||
|
||||
|
@ -365,7 +365,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
|
|||
|
||||
// Pyramid pass
|
||||
batch.setFramebuffer(pyramidFBO);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->_viewFrustum->getFarClip(), 0.0f, 0.0f, 0.0f));
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->getViewFrustum().getFarClip(), 0.0f, 0.0f, 0.0f));
|
||||
batch.setPipeline(pyramidPipeline);
|
||||
batch.setResourceTexture(AmbientOcclusionEffect_DepthMapSlot, depthBuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
|
|
@ -94,7 +94,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() {
|
|||
|
||||
void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
|
@ -118,8 +118,8 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re
|
|||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setModelTransform(Transform());
|
||||
|
@ -134,7 +134,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re
|
|||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
|
||||
args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
args->getViewFrustum().computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
||||
// float depthScale = (farVal - nearVal) / farVal;
|
||||
// float nearScale = -1.0f / nearVal;
|
||||
|
|
|
@ -284,7 +284,7 @@ void DebugDeferredBuffer::configure(const Config& config) {
|
|||
|
||||
void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
|
@ -292,20 +292,20 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
|
|||
const auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
const auto textureCache = DependencyManager::get<TextureCache>();
|
||||
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
// TODO REMOVE: Temporary until UI
|
||||
auto first = _customPipelines.begin()->first;
|
||||
|
||||
|
||||
batch.setPipeline(getPipeline(_mode, first));
|
||||
|
||||
|
||||
batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture());
|
||||
batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture());
|
||||
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
|
||||
|
|
|
@ -218,15 +218,15 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
|||
float tHeight = args->_viewport.w / (float)framebufferSize.height();
|
||||
|
||||
// The view frustum is the mono frustum base
|
||||
auto viewFrustum = args->_viewFrustum;
|
||||
auto viewFrustum = args->getViewFrustum();
|
||||
|
||||
// Eval the mono projection
|
||||
mat4 monoProjMat;
|
||||
viewFrustum->evalProjectionMatrix(monoProjMat);
|
||||
viewFrustum.evalProjectionMatrix(monoProjMat);
|
||||
|
||||
// The mono view transform
|
||||
Transform monoViewTransform;
|
||||
viewFrustum->evalViewTransform(monoViewTransform);
|
||||
viewFrustum.evalViewTransform(monoViewTransform);
|
||||
|
||||
// THe mono view matrix coming from the mono view transform
|
||||
glm::mat4 monoViewMat;
|
||||
|
@ -296,8 +296,8 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
|||
fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
|
||||
}
|
||||
|
||||
auto eyePoint = viewFrustum->getPosition();
|
||||
float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft());
|
||||
auto eyePoint = viewFrustum.getPosition();
|
||||
float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft());
|
||||
|
||||
|
||||
for (int side = 0; side < numPasses; side++) {
|
||||
|
|
|
@ -62,19 +62,19 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
|
|||
|
||||
void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
|
||||
batch.setPipeline(getHitEffectPipeline());
|
||||
|
||||
glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
|
|
@ -20,7 +20,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum
|
|||
_schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
|
||||
}
|
||||
|
||||
void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) {
|
||||
void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth) {
|
||||
assert(nearDepth < farDepth);
|
||||
|
||||
// Orient the keylight frustum
|
||||
|
@ -38,14 +38,13 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near
|
|||
_frustum->setOrientation(orientation);
|
||||
|
||||
// Position the keylight frustum
|
||||
_frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction);
|
||||
_frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
|
||||
|
||||
const Transform view{ _frustum->getView()};
|
||||
const Transform viewInverse{ view.getInverseMatrix() };
|
||||
|
||||
viewFrustum->calculate();
|
||||
auto nearCorners = viewFrustum->getCorners(nearDepth);
|
||||
auto farCorners = viewFrustum->getCorners(farDepth);
|
||||
auto nearCorners = viewFrustum.getCorners(nearDepth);
|
||||
auto farCorners = viewFrustum.getCorners(farDepth);
|
||||
|
||||
vec3 min{ viewInverse.transform(nearCorners.bottomLeft) };
|
||||
vec3 max{ min };
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
Shadow(model::LightPointer light);
|
||||
|
||||
void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth);
|
||||
void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth);
|
||||
|
||||
const std::shared_ptr<ViewFrustum> getFrustum() const { return _frustum; }
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
|
||||
|
||||
// Is it possible that we render without a viewFrustum ?
|
||||
if (!(renderContext->args && renderContext->args->_viewFrustum)) {
|
||||
if (!(renderContext->args && renderContext->args->hasViewFrustum())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
|
||||
void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
|
||||
|
@ -187,8 +187,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
@ -202,7 +202,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
|
||||
void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
|
||||
|
@ -215,8 +215,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R
|
|||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
@ -240,7 +240,7 @@ DrawOverlay3D::DrawOverlay3D(bool opaque) :
|
|||
|
||||
void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const render::ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
|
||||
|
@ -268,8 +268,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
|||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
@ -290,7 +290,7 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
|
|||
|
||||
void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
// from the touched pixel generate the stencil buffer
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
@ -316,7 +316,7 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren
|
|||
|
||||
void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
|
@ -334,8 +334,8 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
|
|||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
|
|
@ -34,7 +34,7 @@ using namespace render;
|
|||
void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
|
||||
const render::ShapeBounds& inShapes) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
const auto globalLight = lightStage.lights[0];
|
||||
|
@ -146,16 +146,15 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
|
|||
}
|
||||
|
||||
// Cache old render args
|
||||
ViewFrustum* viewFrustum = args->_viewFrustum;
|
||||
RenderArgs::RenderMode mode = args->_renderMode;
|
||||
|
||||
auto nearClip = viewFrustum->getNearClip();
|
||||
auto nearClip = args->getViewFrustum().getNearClip();
|
||||
float nearDepth = -args->_boomOffset.z;
|
||||
const int SHADOW_FAR_DEPTH = 20;
|
||||
globalLight->shadow.setKeylightFrustum(viewFrustum, nearDepth, nearClip + SHADOW_FAR_DEPTH);
|
||||
globalLight->shadow.setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH);
|
||||
|
||||
// Set the keylight render args
|
||||
args->_viewFrustum = globalLight->shadow.getFrustum().get();
|
||||
args->pushViewFrustum(*(globalLight->shadow.getFrustum()));
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
|
||||
// TODO: Allow runtime manipulation of culling ShouldRenderFunctor
|
||||
|
@ -165,6 +164,6 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
|
|||
}
|
||||
|
||||
// Reset the render args
|
||||
args->_viewFrustum = viewFrustum;
|
||||
args->popViewFrustum();
|
||||
args->_renderMode = mode;
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include <OctreeUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <gpu/Context.h>
|
||||
|
@ -23,10 +24,10 @@ using namespace render;
|
|||
void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details,
|
||||
const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
ViewFrustum* frustum = args->_viewFrustum;
|
||||
const ViewFrustum& frustum = args->getViewFrustum();
|
||||
|
||||
details._considered += (int)inItems.size();
|
||||
|
||||
|
@ -42,7 +43,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
|
|||
bool inView;
|
||||
{
|
||||
PerformanceTimer perfTimer("boxIntersectsFrustum");
|
||||
inView = frustum->boxIntersectsFrustum(item.bound);
|
||||
inView = frustum.boxIntersectsFrustum(item.bound);
|
||||
}
|
||||
if (inView) {
|
||||
bool bigEnoughToRender;
|
||||
|
@ -64,7 +65,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
|
|||
|
||||
void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
auto& scene = sceneContext->_scene;
|
||||
|
||||
outItems.clear();
|
||||
|
@ -85,7 +86,7 @@ void FetchSpatialTree::configure(const Config& config) {
|
|||
|
||||
void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemSpatialTree::ItemSelection& outSelection) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = sceneContext->_scene;
|
||||
|
||||
|
@ -93,22 +94,18 @@ void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const Render
|
|||
outSelection.clear();
|
||||
|
||||
// Eventually use a frozen frustum
|
||||
auto queryFrustum = *args->_viewFrustum;
|
||||
auto queryFrustum = args->getViewFrustum();
|
||||
if (_freezeFrustum) {
|
||||
if (_justFrozeFrustum) {
|
||||
_justFrozeFrustum = false;
|
||||
_frozenFrutstum = *args->_viewFrustum;
|
||||
_frozenFrutstum = args->getViewFrustum();
|
||||
}
|
||||
queryFrustum = _frozenFrutstum;
|
||||
}
|
||||
|
||||
// Octree selection!
|
||||
|
||||
float angle = glm::degrees(queryFrustum.getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
|
||||
|
||||
float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
scene->getSpatialTree().selectCellItems(outSelection, _filter, queryFrustum, angle);
|
||||
|
||||
}
|
||||
|
||||
void CullSpatialSelection::configure(const Config& config) {
|
||||
|
@ -120,7 +117,7 @@ void CullSpatialSelection::configure(const Config& config) {
|
|||
void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext,
|
||||
const ItemSpatialTree::ItemSelection& inSelection, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = sceneContext->_scene;
|
||||
|
||||
|
@ -128,13 +125,12 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
|
|||
details._considered += (int)inSelection.numItems();
|
||||
|
||||
// Eventually use a frozen frustum
|
||||
auto argFrustum = args->_viewFrustum;
|
||||
if (_freezeFrustum) {
|
||||
if (_justFrozeFrustum) {
|
||||
_justFrozeFrustum = false;
|
||||
_frozenFrutstum = *args->_viewFrustum;
|
||||
_frozenFrutstum = args->getViewFrustum();
|
||||
}
|
||||
args->_viewFrustum = &_frozenFrutstum; // replace the true view frustum by the frozen one
|
||||
args->pushViewFrustum(_frozenFrutstum); // replace the true view frustum by the frozen one
|
||||
}
|
||||
|
||||
// Culling Frustum / solidAngle test helper class
|
||||
|
@ -151,8 +147,8 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
|
|||
_renderDetails(renderDetails)
|
||||
{
|
||||
// FIXME: Keep this code here even though we don't use it yet
|
||||
/*_eyePos = _args->_viewFrustum->getPosition();
|
||||
float a = glm::degrees(_args->_viewFrustum->getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
||||
/*_eyePos = _args->getViewFrustum().getPosition();
|
||||
float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
||||
auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees
|
||||
angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree
|
||||
auto tanAlpha = tan(angle);
|
||||
|
@ -161,7 +157,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
|
|||
}
|
||||
|
||||
bool frustumTest(const AABox& bound) {
|
||||
if (!_args->_viewFrustum->boxIntersectsFrustum(bound)) {
|
||||
if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) {
|
||||
_renderDetails._outOfView++;
|
||||
return false;
|
||||
}
|
||||
|
@ -305,7 +301,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
|
|||
|
||||
// Restore frustum if using the frozen one:
|
||||
if (_freezeFrustum) {
|
||||
args->_viewFrustum = argFrustum;
|
||||
args->popViewFrustum();
|
||||
}
|
||||
|
||||
std::static_pointer_cast<Config>(renderContext->jobConfig)->numItems = (int)outItems.size();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include <OctreeUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RenderArgs.h>
|
||||
|
||||
|
@ -86,7 +87,7 @@ void DrawSceneOctree::configure(const Config& config) {
|
|||
void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
|
||||
const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = sceneContext->_scene;
|
||||
|
||||
|
@ -97,8 +98,8 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
|
|||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
|
@ -148,7 +149,7 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
|
|||
}
|
||||
// Draw the LOD Reticle
|
||||
{
|
||||
float angle = glm::degrees(args->_viewFrustum->getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
Transform crosshairModel;
|
||||
crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0));
|
||||
crosshairModel.setScale(1000.0 * tan(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO
|
||||
|
@ -198,15 +199,15 @@ void DrawItemSelection::configure(const Config& config) {
|
|||
void DrawItemSelection::run(const SceneContextPointer& sceneContext,
|
||||
const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = sceneContext->_scene;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
|
|
|
@ -107,7 +107,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext,
|
|||
const RenderContextPointer& renderContext,
|
||||
const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = sceneContext->_scene;
|
||||
const int NUM_STATUS_VEC4_PER_ITEM = 2;
|
||||
|
@ -183,8 +183,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext,
|
|||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
|
|
|
@ -120,7 +120,7 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons
|
|||
|
||||
void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
// render lights
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// CullTask.cpp
|
||||
// SortTask.cpp
|
||||
// render/src/render
|
||||
//
|
||||
// Created by Sam Gateau on 2/2/16.
|
||||
|
@ -42,7 +42,7 @@ struct BackToFrontSort {
|
|||
|
||||
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
auto& scene = sceneContext->_scene;
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
@ -60,7 +60,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
|
|||
for (auto itemDetails : inItems) {
|
||||
auto item = scene->getItem(itemDetails.id);
|
||||
auto bound = itemDetails.bound; // item.getBound();
|
||||
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
|
||||
float distance = args->getViewFrustum().distanceToCamera(bound.calcCenter());
|
||||
|
||||
itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QEventLoop>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
@ -706,9 +709,15 @@ void ScriptEngine::run() {
|
|||
|
||||
QScriptValue result = evaluate(_scriptContents, _fileNameString);
|
||||
|
||||
QElapsedTimer startTime;
|
||||
startTime.start();
|
||||
#ifdef _WIN32
|
||||
// VS13 does not sleep_until unless it uses the system_clock, see:
|
||||
// https://www.reddit.com/r/cpp_questions/comments/3o71ic/sleep_until_not_working_with_a_time_pointsteady/
|
||||
using clock = std::chrono::system_clock;
|
||||
#else
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
#endif
|
||||
|
||||
clock::time_point startTime = clock::now();
|
||||
int thisFrame = 0;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -716,12 +725,29 @@ void ScriptEngine::run() {
|
|||
|
||||
qint64 lastUpdate = usecTimestampNow();
|
||||
|
||||
// TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine
|
||||
while (!_isFinished) {
|
||||
int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
// Throttle to SCRIPT_FPS
|
||||
const std::chrono::microseconds FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
|
||||
clock::time_point sleepTime(startTime + thisFrame++ * FRAME_DURATION);
|
||||
std::this_thread::sleep_until(sleepTime);
|
||||
|
||||
#ifdef SCRIPT_DELAY_DEBUG
|
||||
{
|
||||
auto now = clock::now();
|
||||
uint64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(now - startTime).count();
|
||||
if (seconds > 0) { // avoid division by zero and time travel
|
||||
uint64_t fps = thisFrame / seconds;
|
||||
// Overreporting artificially reduces the reported rate
|
||||
if (thisFrame % SCRIPT_FPS == 0) {
|
||||
qCDebug(scriptengine) <<
|
||||
"Frame:" << thisFrame <<
|
||||
"Slept (us):" << std::chrono::duration_cast<std::chrono::microseconds>(now - sleepTime).count() <<
|
||||
"FPS:" << fps;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (_isFinished) {
|
||||
break;
|
||||
}
|
||||
|
@ -969,7 +995,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
}
|
||||
QList<QUrl> urls;
|
||||
bool knowsSensitivity = false;
|
||||
Qt::CaseSensitivity sensitivity;
|
||||
Qt::CaseSensitivity sensitivity { Qt::CaseSensitive };
|
||||
auto getSensitivity = [&]() {
|
||||
if (!knowsSensitivity) {
|
||||
QString path = currentSandboxURL.path();
|
||||
|
@ -986,6 +1012,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
const auto strippingFlags = QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment;
|
||||
for (QString file : includeFiles) {
|
||||
QUrl thisURL;
|
||||
bool isStandardLibrary = false;
|
||||
if (file.startsWith("/~/")) {
|
||||
thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file)));
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
|
@ -993,21 +1020,17 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
qDebug() << "ScriptEngine::include -- skipping" << file << "-- outside of standard libraries";
|
||||
continue;
|
||||
}
|
||||
isStandardLibrary = true;
|
||||
} else {
|
||||
thisURL = resolvePath(file);
|
||||
}
|
||||
|
||||
if (!_includedURLs.contains(thisURL)) {
|
||||
if (!currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") &&
|
||||
(
|
||||
(currentSandboxURL.scheme() != "file") ||
|
||||
(
|
||||
!thisURL.toString(strippingFlags).startsWith(defaultScriptsLocation().toString(), getSensitivity()) &&
|
||||
!thisURL.toString(strippingFlags).startsWith(currentSandboxURL.toString(strippingFlags), getSensitivity())
|
||||
)
|
||||
)
|
||||
) {
|
||||
qCWarning(scriptengine) << "Script.include() ignoring file path" << thisURL << "outside of original entity script" << currentSandboxURL;
|
||||
if (!isStandardLibrary && !currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") &&
|
||||
(currentSandboxURL.scheme() != "file" ||
|
||||
!thisURL.toString(strippingFlags).startsWith(currentSandboxURL.toString(strippingFlags), getSensitivity()))) {
|
||||
qCWarning(scriptengine) << "Script.include() ignoring file path"
|
||||
<< thisURL << "outside of original entity script" << currentSandboxURL;
|
||||
} else {
|
||||
// We could also check here for CORS, but we don't yet.
|
||||
// It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here.
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
#include "ScriptUUID.h"
|
||||
#include "Vec3.h"
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
static const QString NO_SCRIPT("");
|
||||
|
||||
const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0f / 60.0f) * 1000 * 1000) + 0.5f);
|
||||
static const int SCRIPT_FPS = 60;
|
||||
|
||||
class CallbackData {
|
||||
public:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// OctreeProjectedPolygon.cpp
|
||||
// libraries/octree/src
|
||||
// CubeProjectedPolygon.cpp
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 06/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
|
@ -15,50 +15,50 @@
|
|||
|
||||
#include "GeometryUtil.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "OctreeLogging.h"
|
||||
#include "OctreeProjectedPolygon.h"
|
||||
#include "SharedLogging.h"
|
||||
#include "CubeProjectedPolygon.h"
|
||||
|
||||
|
||||
glm::vec2 BoundingBox::getVertex(int vertexNumber) const {
|
||||
glm::vec2 BoundingRectangle::getVertex(int vertexNumber) const {
|
||||
switch (vertexNumber) {
|
||||
case BoundingBox::BOTTOM_LEFT:
|
||||
case BoundingRectangle::BOTTOM_LEFT:
|
||||
return corner;
|
||||
case BoundingBox::TOP_LEFT:
|
||||
case BoundingRectangle::TOP_LEFT:
|
||||
return glm::vec2(corner.x, corner.y + size.y);
|
||||
case BoundingBox::BOTTOM_RIGHT:
|
||||
case BoundingRectangle::BOTTOM_RIGHT:
|
||||
return glm::vec2(corner.x + size.x, corner.y);
|
||||
case BoundingBox::TOP_RIGHT:
|
||||
case BoundingRectangle::TOP_RIGHT:
|
||||
return corner + size;
|
||||
}
|
||||
assert(false); // not allowed
|
||||
return glm::vec2(0,0);
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::topHalf() const {
|
||||
BoundingRectangle BoundingRectangle::topHalf() const {
|
||||
float halfY = size.y/2.0f;
|
||||
BoundingBox result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
|
||||
BoundingRectangle result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::bottomHalf() const {
|
||||
BoundingRectangle BoundingRectangle::bottomHalf() const {
|
||||
float halfY = size.y/2.0f;
|
||||
BoundingBox result(corner, glm::vec2(size.x, halfY));
|
||||
BoundingRectangle result(corner, glm::vec2(size.x, halfY));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::leftHalf() const {
|
||||
BoundingRectangle BoundingRectangle::leftHalf() const {
|
||||
float halfX = size.x/2.0f;
|
||||
BoundingBox result(corner, glm::vec2(halfX, size.y));
|
||||
BoundingRectangle result(corner, glm::vec2(halfX, size.y));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::rightHalf() const {
|
||||
BoundingRectangle BoundingRectangle::rightHalf() const {
|
||||
float halfX = size.x/2.0f;
|
||||
BoundingBox result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
|
||||
BoundingRectangle result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BoundingBox::contains(const BoundingBox& box) const {
|
||||
bool BoundingRectangle::contains(const BoundingRectangle& box) const {
|
||||
return ( _set &&
|
||||
(box.corner.x >= corner.x) &&
|
||||
(box.corner.y >= corner.y) &&
|
||||
|
@ -67,7 +67,7 @@ bool BoundingBox::contains(const BoundingBox& box) const {
|
|||
);
|
||||
}
|
||||
|
||||
bool BoundingBox::contains(const glm::vec2& point) const {
|
||||
bool BoundingRectangle::contains(const glm::vec2& point) const {
|
||||
return ( _set &&
|
||||
(point.x > corner.x) &&
|
||||
(point.y > corner.y) &&
|
||||
|
@ -76,7 +76,7 @@ bool BoundingBox::contains(const glm::vec2& point) const {
|
|||
);
|
||||
}
|
||||
|
||||
void BoundingBox::explandToInclude(const BoundingBox& box) {
|
||||
void BoundingRectangle::explandToInclude(const BoundingRectangle& box) {
|
||||
if (!_set) {
|
||||
corner = box.corner;
|
||||
size = box.size;
|
||||
|
@ -94,20 +94,20 @@ void BoundingBox::explandToInclude(const BoundingBox& box) {
|
|||
}
|
||||
|
||||
|
||||
void BoundingBox::printDebugDetails(const char* label) const {
|
||||
qCDebug(octree, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
|
||||
(label ? label : "BoundingBox"),
|
||||
void BoundingRectangle::printDebugDetails(const char* label) const {
|
||||
qCDebug(shared, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
|
||||
(label ? label : "BoundingRectangle"),
|
||||
debug::valueOf(_set), (double)corner.x, (double)corner.y, (double)size.x, (double)size.y,
|
||||
(double)corner.x, (double)corner.y, (double)(corner.x+size.x), (double)(corner.y+size.y));
|
||||
}
|
||||
|
||||
|
||||
long OctreeProjectedPolygon::pointInside_calls = 0;
|
||||
long OctreeProjectedPolygon::occludes_calls = 0;
|
||||
long OctreeProjectedPolygon::intersects_calls = 0;
|
||||
long CubeProjectedPolygon::pointInside_calls = 0;
|
||||
long CubeProjectedPolygon::occludes_calls = 0;
|
||||
long CubeProjectedPolygon::intersects_calls = 0;
|
||||
|
||||
|
||||
OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) :
|
||||
CubeProjectedPolygon::CubeProjectedPolygon(const BoundingRectangle& box) :
|
||||
_vertexCount(4),
|
||||
_maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
|
||||
_distance(0)
|
||||
|
@ -118,7 +118,7 @@ OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) :
|
|||
}
|
||||
|
||||
|
||||
void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
|
||||
void CubeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
|
||||
_vertices[vertex] = point;
|
||||
|
||||
// keep track of our bounding box
|
||||
|
@ -138,9 +138,9 @@ void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
|
|||
}
|
||||
|
||||
// can be optimized with new pointInside()
|
||||
bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView) const {
|
||||
bool CubeProjectedPolygon::occludes(const CubeProjectedPolygon& occludee, bool checkAllInView) const {
|
||||
|
||||
OctreeProjectedPolygon::occludes_calls++;
|
||||
CubeProjectedPolygon::occludes_calls++;
|
||||
|
||||
// if we are completely out of view, then we definitely don't occlude!
|
||||
// if the occludee is completely out of view, then we also don't occlude it
|
||||
|
@ -197,12 +197,12 @@ bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bo
|
|||
return false; // if we got this far, then we're not occluded
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::occludes(const BoundingBox& boxOccludee) const {
|
||||
OctreeProjectedPolygon testee(boxOccludee);
|
||||
bool CubeProjectedPolygon::occludes(const BoundingRectangle& boxOccludee) const {
|
||||
CubeProjectedPolygon testee(boxOccludee);
|
||||
return occludes(testee);
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const {
|
||||
bool CubeProjectedPolygon::matches(const CubeProjectedPolygon& testee) const {
|
||||
if (testee.getVertexCount() != getVertexCount()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -231,14 +231,14 @@ bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const
|
|||
return true; // all of our vertices match, therefore we're the same
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::matches(const BoundingBox& box) const {
|
||||
OctreeProjectedPolygon testee(box);
|
||||
bool CubeProjectedPolygon::matches(const BoundingRectangle& box) const {
|
||||
CubeProjectedPolygon testee(box);
|
||||
return matches(testee);
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
|
||||
bool CubeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
|
||||
|
||||
OctreeProjectedPolygon::pointInside_calls++;
|
||||
CubeProjectedPolygon::pointInside_calls++;
|
||||
|
||||
// first check the bounding boxes, the point must be fully within the boounding box of this polygon
|
||||
if ((point.x > getMaxX()) ||
|
||||
|
@ -264,23 +264,23 @@ bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVe
|
|||
return true;
|
||||
}
|
||||
|
||||
void OctreeProjectedPolygon::printDebugDetails() const {
|
||||
qCDebug(octree, "OctreeProjectedPolygon..."
|
||||
void CubeProjectedPolygon::printDebugDetails() const {
|
||||
qCDebug(shared, "CubeProjectedPolygon..."
|
||||
" minX=%f maxX=%f minY=%f maxY=%f", (double)getMinX(), (double)getMaxX(), (double)getMinY(), (double)getMaxY());
|
||||
qCDebug(octree, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
|
||||
qCDebug(shared, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
|
||||
for (int i = 0; i < getVertexCount(); i++) {
|
||||
glm::vec2 point = getVertex(i);
|
||||
qCDebug(octree, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
|
||||
qCDebug(shared, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
|
||||
}
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::intersects(const BoundingBox& box) const {
|
||||
OctreeProjectedPolygon testee(box);
|
||||
bool CubeProjectedPolygon::intersects(const BoundingRectangle& box) const {
|
||||
CubeProjectedPolygon testee(box);
|
||||
return intersects(testee);
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) const {
|
||||
OctreeProjectedPolygon::intersects_calls++;
|
||||
bool CubeProjectedPolygon::intersects(const CubeProjectedPolygon& testee) const {
|
||||
CubeProjectedPolygon::intersects_calls++;
|
||||
return intersectsOnAxes(testee) && testee.intersectsOnAxes(*this);
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) co
|
|||
// Note: this only works on convex polygons
|
||||
//
|
||||
//
|
||||
bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& testee) const {
|
||||
bool CubeProjectedPolygon::intersectsOnAxes(const CubeProjectedPolygon& testee) const {
|
||||
|
||||
// consider each edge of this polygon as a potential separating axis
|
||||
for (int i = 0; i < getVertexCount(); i++) {
|
||||
|
@ -324,7 +324,7 @@ bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& test
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const {
|
||||
bool CubeProjectedPolygon::canMerge(const CubeProjectedPolygon& that) const {
|
||||
|
||||
// RIGHT/NEAR
|
||||
// LEFT/NEAR
|
||||
|
@ -642,7 +642,7 @@ bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const
|
|||
}
|
||||
|
||||
|
||||
void OctreeProjectedPolygon::merge(const OctreeProjectedPolygon& that) {
|
||||
void CubeProjectedPolygon::merge(const CubeProjectedPolygon& that) {
|
||||
|
||||
// RIGHT/NEAR
|
||||
// LEFT/NEAR
|
|
@ -1,55 +1,55 @@
|
|||
//
|
||||
// OctreeProjectedPolygon.h
|
||||
// libraries/octree/src
|
||||
// CubeProjectedPolygon.h
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 06/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// The projected shadow (on the 2D view plane) for a voxel
|
||||
// The projected shadow (on the 2D view plane) for a cube
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_OctreeProjectedPolygon_h
|
||||
#define hifi_OctreeProjectedPolygon_h
|
||||
#ifndef hifi_CubeProjectedPolygon_h
|
||||
#define hifi_CubeProjectedPolygon_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
// 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;
|
||||
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 {
|
||||
class BoundingRectangle {
|
||||
public:
|
||||
enum { BOTTOM_LEFT, BOTTOM_RIGHT, TOP_RIGHT, TOP_LEFT, VERTEX_COUNT };
|
||||
|
||||
BoundingBox(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
|
||||
BoundingBox() : _set(false) {}
|
||||
BoundingRectangle(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
|
||||
BoundingRectangle() : _set(false) {}
|
||||
glm::vec2 corner;
|
||||
glm::vec2 size;
|
||||
bool contains(const BoundingBox& box) const;
|
||||
bool contains(const BoundingRectangle& box) const;
|
||||
bool contains(const glm::vec2& point) const;
|
||||
bool pointInside(const glm::vec2& point) const { return contains(point); }
|
||||
|
||||
void explandToInclude(const BoundingBox& box);
|
||||
void explandToInclude(const BoundingRectangle& 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;
|
||||
BoundingRectangle topHalf() const;
|
||||
BoundingRectangle bottomHalf() const;
|
||||
BoundingRectangle leftHalf() const;
|
||||
BoundingRectangle 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;
|
||||
|
@ -63,18 +63,18 @@ const int PROJECTION_NEAR = 16;
|
|||
const int PROJECTION_FAR = 32;
|
||||
const int PROJECTION_CLIPPED = 64;
|
||||
|
||||
class OctreeProjectedPolygon {
|
||||
class CubeProjectedPolygon {
|
||||
|
||||
public:
|
||||
OctreeProjectedPolygon(const BoundingBox& box);
|
||||
CubeProjectedPolygon(const BoundingRectangle& box);
|
||||
|
||||
OctreeProjectedPolygon(int vertexCount = 0) :
|
||||
_vertexCount(vertexCount),
|
||||
CubeProjectedPolygon(int vertexCount = 0) :
|
||||
_vertexCount(vertexCount),
|
||||
_maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
|
||||
_distance(0)
|
||||
{ }
|
||||
|
||||
~OctreeProjectedPolygon() { }
|
||||
|
||||
~CubeProjectedPolygon() { }
|
||||
const ProjectedVertices& getVertices() const { return _vertices; }
|
||||
const glm::vec2& getVertex(int i) const { return _vertices[i]; }
|
||||
void setVertex(int vertex, const glm::vec2& point);
|
||||
|
@ -92,28 +92,28 @@ public:
|
|||
|
||||
|
||||
bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const;
|
||||
bool occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView = false) const;
|
||||
bool occludes(const BoundingBox& occludee) const;
|
||||
bool intersects(const OctreeProjectedPolygon& testee) const;
|
||||
bool intersects(const BoundingBox& box) const;
|
||||
bool matches(const OctreeProjectedPolygon& testee) const;
|
||||
bool matches(const BoundingBox& testee) const;
|
||||
bool intersectsOnAxes(const OctreeProjectedPolygon& testee) const;
|
||||
bool occludes(const CubeProjectedPolygon& occludee, bool checkAllInView = false) const;
|
||||
bool occludes(const BoundingRectangle& occludee) const;
|
||||
bool intersects(const CubeProjectedPolygon& testee) const;
|
||||
bool intersects(const BoundingRectangle& box) const;
|
||||
bool matches(const CubeProjectedPolygon& testee) const;
|
||||
bool matches(const BoundingRectangle& testee) const;
|
||||
bool intersectsOnAxes(const CubeProjectedPolygon& testee) const;
|
||||
|
||||
bool canMerge(const CubeProjectedPolygon& that) const;
|
||||
void merge(const CubeProjectedPolygon& that); // replaces vertices of this with new merged version
|
||||
|
||||
bool canMerge(const OctreeProjectedPolygon& that) const;
|
||||
void merge(const OctreeProjectedPolygon& that); // replaces vertices of this with new merged version
|
||||
|
||||
float getMaxX() const { return _maxX; }
|
||||
float getMaxY() const { return _maxY; }
|
||||
float getMinX() const { return _minX; }
|
||||
float getMinY() const { return _minY; }
|
||||
|
||||
BoundingBox getBoundingBox() const {
|
||||
return BoundingBox(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
|
||||
|
||||
BoundingRectangle getBoundingBox() const {
|
||||
return BoundingRectangle(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
|
||||
}
|
||||
|
||||
void printDebugDetails() const;
|
||||
|
||||
|
||||
static long pointInside_calls;
|
||||
static long occludes_calls;
|
||||
static long intersects_calls;
|
||||
|
@ -132,4 +132,4 @@ private:
|
|||
};
|
||||
|
||||
|
||||
#endif // hifi_OctreeProjectedPolygon_h
|
||||
#endif // hifi_CubeProjectedPolygon_h
|
|
@ -35,7 +35,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator
|
|||
updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue);
|
||||
}
|
||||
Q_ASSERT(!glm::isnan(computedValue));
|
||||
|
||||
|
||||
// update state for next time
|
||||
_lastError = error;
|
||||
_lastAccumulation = accumulatedError;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Plane.cpp
|
||||
// libraries/octree/src/
|
||||
// libraries/shared/src/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
|
@ -13,12 +13,12 @@
|
|||
//
|
||||
|
||||
#include "Plane.h"
|
||||
#include "OctreeLogging.h"
|
||||
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include "SharedLogging.h"
|
||||
|
||||
|
||||
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
||||
glm::vec3 linev1v2, linev1v3;
|
||||
|
@ -65,7 +65,7 @@ float Plane::distance(const glm::vec3 &point) const {
|
|||
}
|
||||
|
||||
void Plane::print() const {
|
||||
qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
|
||||
qCDebug(shared, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
|
||||
(double)_point.x, (double)_point.y, (double)_point.z,
|
||||
(double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Plane.h
|
||||
// libraries/octree/src/
|
||||
// libraries/shared/src/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
|
@ -20,7 +20,7 @@
|
|||
class Plane {
|
||||
public:
|
||||
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); }
|
||||
Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {};
|
||||
Plane() : _normal(0.0f), _point(0.0f), _dCoefficient(0.0f) {};
|
||||
~Plane() {} ;
|
||||
|
||||
// methods for defining the plane
|
||||
|
@ -28,12 +28,13 @@ public:
|
|||
void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
|
||||
void setCoefficients(float a, float b, float c, float d);
|
||||
|
||||
// getters
|
||||
// getters
|
||||
const glm::vec3& getNormal() const { return _normal; };
|
||||
const glm::vec3& getPoint() const { return _point; };
|
||||
float getDCoefficient() const { return _dCoefficient; };
|
||||
|
||||
// utilities
|
||||
void invalidate() { _normal = glm::vec3(0.0f), _dCoefficient = 1.0e6f; } // distance() never less than 10^6
|
||||
float distance(const glm::vec3 &point) const;
|
||||
void print() const;
|
||||
|
||||
|
@ -44,4 +45,4 @@ private:
|
|||
};
|
||||
|
||||
|
||||
#endif // hifi_Plane_h
|
||||
#endif // hifi_Plane_h
|
|
@ -14,12 +14,15 @@
|
|||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "GLMHelpers.h"
|
||||
#include <stack>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
|
||||
|
||||
class AABox;
|
||||
class OctreeRenderer;
|
||||
class ViewFrustum;
|
||||
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
|
@ -39,21 +42,21 @@ public:
|
|||
SHADOW,
|
||||
OTHER
|
||||
};
|
||||
|
||||
|
||||
struct Item {
|
||||
int _considered = 0;
|
||||
int _outOfView = 0;
|
||||
int _tooSmall = 0;
|
||||
int _rendered = 0;
|
||||
};
|
||||
|
||||
|
||||
int _materialSwitches = 0;
|
||||
int _trianglesRendered = 0;
|
||||
|
||||
|
||||
Item _item;
|
||||
Item _shadow;
|
||||
Item _other;
|
||||
|
||||
|
||||
Item& edit(Type type) {
|
||||
switch (type) {
|
||||
case SHADOW:
|
||||
|
@ -77,7 +80,6 @@ public:
|
|||
|
||||
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
|
||||
OctreeRenderer* renderer = nullptr,
|
||||
ViewFrustum* viewFrustum = nullptr,
|
||||
float sizeScale = 1.0f,
|
||||
int boundaryLevelAdjust = 0,
|
||||
RenderMode renderMode = DEFAULT_RENDER_MODE,
|
||||
|
@ -86,7 +88,6 @@ public:
|
|||
gpu::Batch* batch = nullptr) :
|
||||
_context(context),
|
||||
_renderer(renderer),
|
||||
_viewFrustum(viewFrustum),
|
||||
_sizeScale(sizeScale),
|
||||
_boundaryLevelAdjust(boundaryLevelAdjust),
|
||||
_renderMode(renderMode),
|
||||
|
@ -95,11 +96,22 @@ public:
|
|||
_batch(batch) {
|
||||
}
|
||||
|
||||
bool hasViewFrustum() const { return _viewFrustums.size() > 0; }
|
||||
void setViewFrustum(const ViewFrustum& viewFrustum) {
|
||||
while (_viewFrustums.size() > 0) {
|
||||
_viewFrustums.pop();
|
||||
}
|
||||
_viewFrustums.push(viewFrustum);
|
||||
}
|
||||
const ViewFrustum& getViewFrustum() const { assert(_viewFrustums.size() > 0); return _viewFrustums.top(); }
|
||||
void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
|
||||
void popViewFrustum() { _viewFrustums.pop(); }
|
||||
|
||||
std::shared_ptr<gpu::Context> _context = nullptr;
|
||||
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer = nullptr;
|
||||
std::shared_ptr<render::ShapePipeline> _pipeline = nullptr;
|
||||
OctreeRenderer* _renderer = nullptr;
|
||||
ViewFrustum* _viewFrustum = nullptr;
|
||||
std::stack<ViewFrustum> _viewFrustums;
|
||||
glm::ivec4 _viewport{ 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
glm::vec3 _boomOffset{ 0.0f, 0.0f, 1.0f };
|
||||
float _sizeScale = 1.0f;
|
||||
|
@ -108,7 +120,7 @@ public:
|
|||
RenderSide _renderSide = MONO;
|
||||
DebugFlags _debugFlags = RENDER_DEBUG_NONE;
|
||||
gpu::Batch* _batch = nullptr;
|
||||
|
||||
|
||||
std::shared_ptr<gpu::Texture> _whiteTexture;
|
||||
|
||||
RenderDetails _details;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// ViewFrustum.cpp
|
||||
// libraries/octree/src
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
|
@ -17,13 +17,13 @@
|
|||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
#include "GLMHelpers.h"
|
||||
#include "NumericalConstants.h"
|
||||
#include "SharedLogging.h"
|
||||
//#include "OctreeConstants.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "OctreeLogging.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -41,24 +41,24 @@ void ViewFrustum::setPosition(const glm::vec3& position) {
|
|||
}
|
||||
|
||||
// Order cooresponds to the order defined in the BoxVertex enum.
|
||||
static const glm::vec4 NDC_VALUES[8] = {
|
||||
glm::vec4(-1, -1, -1, 1),
|
||||
glm::vec4(1, -1, -1, 1),
|
||||
glm::vec4(1, 1, -1, 1),
|
||||
glm::vec4(-1, 1, -1, 1),
|
||||
glm::vec4(-1, -1, 1, 1),
|
||||
glm::vec4(1, -1, 1, 1),
|
||||
glm::vec4(1, 1, 1, 1),
|
||||
glm::vec4(-1, 1, 1, 1),
|
||||
static const glm::vec4 NDC_VALUES[NUM_FRUSTUM_CORNERS] = {
|
||||
glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f),
|
||||
glm::vec4(1.0f, -1.0f, -1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 1.0f, -1.0f, 1.0f),
|
||||
glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f),
|
||||
glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, -1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f),
|
||||
};
|
||||
|
||||
void ViewFrustum::setProjection(const glm::mat4& projection) {
|
||||
_projection = projection;
|
||||
_inverseProjection = glm::inverse(projection);
|
||||
glm::mat4 inverseProjection = glm::inverse(projection);
|
||||
|
||||
// compute our dimensions the usual way
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_corners[i] = _inverseProjection * NDC_VALUES[i];
|
||||
for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
|
||||
_corners[i] = inverseProjection * NDC_VALUES[i];
|
||||
_corners[i] /= _corners[i].w;
|
||||
}
|
||||
_nearClip = -_corners[BOTTOM_LEFT_NEAR].z;
|
||||
|
@ -66,12 +66,12 @@ void ViewFrustum::setProjection(const glm::mat4& projection) {
|
|||
_aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) /
|
||||
(_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y);
|
||||
|
||||
glm::vec4 top = _inverseProjection * vec4(0, 1, -1, 1);
|
||||
glm::vec4 top = inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f);
|
||||
top /= top.w;
|
||||
_fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0, 0, -1), glm::normalize(vec3(top))))));
|
||||
_fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0.0f, 0.0f, -1.0f), glm::normalize(vec3(top))))));
|
||||
}
|
||||
|
||||
// ViewFrustum::calculateViewFrustum()
|
||||
// ViewFrustum::calculate()
|
||||
//
|
||||
// Description: this will calculate the view frustum bounds for a given position and direction
|
||||
//
|
||||
|
@ -84,7 +84,7 @@ void ViewFrustum::calculate() {
|
|||
// then transform them to world space
|
||||
glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction));
|
||||
glm::vec4 v;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
|
||||
v = worldMatrix * _corners[i];
|
||||
v /= v.w;
|
||||
_cornersWorld[i] = glm::vec3(v);
|
||||
|
@ -133,7 +133,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
|
|||
ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const {
|
||||
// only check against frustum
|
||||
ViewFrustum::intersection result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
// check distance to farthest cube point
|
||||
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
|
||||
|
@ -178,7 +178,7 @@ ViewFrustum::intersection ViewFrustum::calculateCubeKeyholeIntersection(const AA
|
|||
|
||||
bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
|
||||
// only check against frustum
|
||||
for(int i = 0; i < 6; ++i) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
|
||||
float distance = _planes[i].distance(point);
|
||||
if (distance < 0.0f) {
|
||||
return false;
|
||||
|
@ -189,7 +189,7 @@ bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
|
|||
|
||||
bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) const {
|
||||
// only check against frustum
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
float distance = _planes[i].distance(center);
|
||||
if (distance < -radius) {
|
||||
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||
|
@ -201,7 +201,7 @@ bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius)
|
|||
|
||||
bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const {
|
||||
// only check against frustum
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
// check distance to farthest box point
|
||||
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
|
||||
|
@ -217,7 +217,7 @@ bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius)
|
|||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
if ( _planes[i].distance(center) < -radius) {
|
||||
return false;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ bool ViewFrustum::cubeIntersectsKeyhole(const AACube& cube) const {
|
|||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
|
||||
return false;
|
||||
|
@ -246,7 +246,7 @@ bool ViewFrustum::boxIntersectsKeyhole(const AABox& box) const {
|
|||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
|
||||
return false;
|
||||
|
@ -281,36 +281,36 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
|
|||
testMatches(compareTo._focalLength, _focalLength);
|
||||
|
||||
if (!result && debug) {
|
||||
qCDebug(octree, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
|
||||
qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
|
||||
qCDebug(shared, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
|
||||
qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
|
||||
(testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
|
||||
(double)_position.x, (double)_position.y, (double)_position.z);
|
||||
qCDebug(octree, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
|
||||
qCDebug(shared, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
|
||||
(testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._direction.x, (double)compareTo._direction.y, (double)compareTo._direction.z,
|
||||
(double)_direction.x, (double)_direction.y, (double)_direction.z );
|
||||
qCDebug(octree, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
|
||||
qCDebug(shared, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
|
||||
(testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._up.x, (double)compareTo._up.y, (double)compareTo._up.z,
|
||||
(double)_up.x, (double)_up.y, (double)_up.z );
|
||||
qCDebug(octree, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
|
||||
qCDebug(shared, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
|
||||
(testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._right.x, (double)compareTo._right.y, (double)compareTo._right.z,
|
||||
(double)_right.x, (double)_right.y, (double)_right.z );
|
||||
qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
|
||||
qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
|
||||
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._fieldOfView, (double)_fieldOfView);
|
||||
qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
|
||||
qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
|
||||
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._aspectRatio, (double)_aspectRatio);
|
||||
qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
|
||||
qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
|
||||
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._nearClip, (double)_nearClip);
|
||||
qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
|
||||
qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
|
||||
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._farClip, (double)_farClip);
|
||||
qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
|
||||
qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
|
||||
(testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._focalLength, (double)_focalLength);
|
||||
}
|
||||
|
@ -342,34 +342,34 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const
|
|||
|
||||
|
||||
if (!result && debug) {
|
||||
qCDebug(octree, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
|
||||
qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
|
||||
qCDebug(shared, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
|
||||
qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
|
||||
(testMatches(compareTo._position,_position, POSITION_SIMILAR_ENOUGH) ?
|
||||
"IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
|
||||
(double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
|
||||
(double)_position.x, (double)_position.y, (double)_position.z );
|
||||
|
||||
qCDebug(octree, "%s -- positionDistance=%f",
|
||||
qCDebug(shared, "%s -- positionDistance=%f",
|
||||
(testMatches(0,positionDistance, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
|
||||
(double)positionDistance);
|
||||
|
||||
qCDebug(octree, "%s -- angleOrientation=%f",
|
||||
qCDebug(shared, "%s -- angleOrientation=%f",
|
||||
(testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
|
||||
(double)angleOrientation);
|
||||
|
||||
qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
|
||||
qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
|
||||
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._fieldOfView, (double)_fieldOfView);
|
||||
qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
|
||||
qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
|
||||
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._aspectRatio, (double)_aspectRatio);
|
||||
qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
|
||||
qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
|
||||
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._nearClip, (double)_nearClip);
|
||||
qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
|
||||
qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
|
||||
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._farClip, (double)_farClip);
|
||||
qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
|
||||
qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
|
||||
(testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
|
||||
(double)compareTo._focalLength, (double)_focalLength);
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
// find the minimum and maximum z values, which will be our near and far clip distances
|
||||
nearValue = FLT_MAX;
|
||||
farValue = -FLT_MAX;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int i = 0; i < NUM_FRUSTUM_CORNERS; i++) {
|
||||
nearValue = min(nearValue, -_corners[i].z);
|
||||
farValue = max(farValue, -_corners[i].z);
|
||||
}
|
||||
|
@ -427,17 +427,17 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
}
|
||||
|
||||
void ViewFrustum::printDebugDetails() const {
|
||||
qCDebug(octree, "ViewFrustum::printDebugDetails()...");
|
||||
qCDebug(octree, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
|
||||
qCDebug(octree, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
|
||||
qCDebug(octree, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
|
||||
qCDebug(octree, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
|
||||
qCDebug(octree, "_fieldOfView=%f", (double)_fieldOfView);
|
||||
qCDebug(octree, "_aspectRatio=%f", (double)_aspectRatio);
|
||||
qCDebug(octree, "_centerSphereRadius=%f", (double)_centerSphereRadius);
|
||||
qCDebug(octree, "_nearClip=%f", (double)_nearClip);
|
||||
qCDebug(octree, "_farClip=%f", (double)_farClip);
|
||||
qCDebug(octree, "_focalLength=%f", (double)_focalLength);
|
||||
qCDebug(shared, "ViewFrustum::printDebugDetails()...");
|
||||
qCDebug(shared, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
|
||||
qCDebug(shared, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
|
||||
qCDebug(shared, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
|
||||
qCDebug(shared, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
|
||||
qCDebug(shared, "_fieldOfView=%f", (double)_fieldOfView);
|
||||
qCDebug(shared, "_aspectRatio=%f", (double)_aspectRatio);
|
||||
qCDebug(shared, "_centerSphereRadius=%f", (double)_centerSphereRadius);
|
||||
qCDebug(shared, "_nearClip=%f", (double)_nearClip);
|
||||
qCDebug(shared, "_farClip=%f", (double)_farClip);
|
||||
qCDebug(shared, "_focalLength=%f", (double)_focalLength);
|
||||
}
|
||||
|
||||
glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
|
||||
|
@ -536,7 +536,7 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT
|
|||
{6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left
|
||||
};
|
||||
|
||||
OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
||||
CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
||||
const glm::vec3& bottomNearRight = box.getCorner();
|
||||
glm::vec3 topFarLeft = box.calcTopFarLeft();
|
||||
|
||||
|
@ -549,7 +549,7 @@ OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const
|
|||
|
||||
int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
|
||||
|
||||
OctreeProjectedPolygon projectedPolygon(vertexCount);
|
||||
CubeProjectedPolygon projectedPolygon(vertexCount);
|
||||
|
||||
bool pointInView = true;
|
||||
bool allPointsInView = false; // assume the best, but wait till we know we have a vertex
|
||||
|
@ -630,7 +630,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth
|
|||
}
|
||||
}
|
||||
|
||||
const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) {
|
||||
const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) const {
|
||||
glm::vec3 normal = glm::normalize(_direction);
|
||||
|
||||
auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) {
|
||||
|
@ -662,51 +662,10 @@ void ViewFrustum::evalViewTransform(Transform& view) const {
|
|||
view.setRotation(getOrientation());
|
||||
}
|
||||
|
||||
float ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, int boundaryLevelAdjust) const {
|
||||
float distanceToCamera = glm::length(bounds.calcCenter() - getPosition());
|
||||
float largestDimension = bounds.getLargestDimension();
|
||||
|
||||
const float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
||||
|
||||
static std::once_flag once;
|
||||
static QMap<float, float> shouldRenderTable;
|
||||
std::call_once(once, [&] {
|
||||
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
|
||||
float scale = maxScale;
|
||||
float factor = 1.0f;
|
||||
|
||||
while (scale > SMALLEST_SCALE_IN_TABLE) {
|
||||
scale /= 2.0f;
|
||||
factor /= 2.0f;
|
||||
shouldRenderTable[scale] = factor;
|
||||
}
|
||||
});
|
||||
|
||||
float closestScale = maxScale;
|
||||
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
|
||||
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
|
||||
if (lowerBound != shouldRenderTable.constEnd()) {
|
||||
closestScale = lowerBound.key();
|
||||
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
|
||||
void ViewFrustum::invalidate() {
|
||||
// these setting should make nearly all intersection tests fail
|
||||
for (int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
|
||||
_planes[i].invalidate();
|
||||
}
|
||||
|
||||
if (closestScale < largestDimension) {
|
||||
visibleDistanceAtClosestScale *= 2.0f;
|
||||
}
|
||||
|
||||
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
|
||||
// a floating point for objects that have small angular size to indicate that they may be rendered
|
||||
// with lower preciscion
|
||||
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
||||
return voxelSizeScale / powf(2, renderLevel);
|
||||
}
|
||||
|
||||
float ViewFrustum::getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) const {
|
||||
const float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
||||
return atan(maxScale / visibleDistanceAtMaxScale);
|
||||
_centerSphereRadius = -1.0e6f; // -10^6 should be negative enough
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// ViewFrustum.h
|
||||
// libraries/octree/src
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
|
@ -17,21 +17,21 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Transform.h"
|
||||
#include "AABox.h"
|
||||
#include "AACube.h"
|
||||
#include "CubeProjectedPolygon.h"
|
||||
#include "Plane.h"
|
||||
#include "OctreeConstants.h"
|
||||
#include "OctreeProjectedPolygon.h"
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include "Transform.h"
|
||||
|
||||
const int NUM_FRUSTUM_CORNERS = 8;
|
||||
const int NUM_FRUSTUM_PLANES = 6;
|
||||
|
||||
const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f;
|
||||
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
|
||||
const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
|
||||
const float DEFAULT_NEAR_CLIP = 0.08f;
|
||||
const float DEFAULT_FAR_CLIP = (float)HALF_TREE_SCALE;
|
||||
const float DEFAULT_FAR_CLIP = 16384.0f;
|
||||
|
||||
// the "ViewFrustum" has a "keyhole" shape: a regular frustum for stuff that is "visible" with
|
||||
// a central sphere for stuff that is nearby (for physics simulation).
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
glm::vec3 bottomRight;
|
||||
// Get the corners depth units from frustum position, along frustum orientation
|
||||
};
|
||||
const Corners getCorners(const float& depth);
|
||||
const Corners getCorners(const float& depth) const;
|
||||
|
||||
// getters for corners
|
||||
const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
|
||||
|
@ -123,7 +123,7 @@ public:
|
|||
void printDebugDetails() const;
|
||||
|
||||
glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
|
||||
OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const;
|
||||
CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
|
||||
void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
|
||||
|
||||
float distanceToCamera(const glm::vec3& point) const;
|
||||
|
@ -131,44 +131,37 @@ public:
|
|||
void evalProjectionMatrix(glm::mat4& proj) const;
|
||||
void evalViewTransform(Transform& view) const;
|
||||
|
||||
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
|
||||
/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
|
||||
float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
|
||||
int boundaryLevelAdjust = 0) const;
|
||||
|
||||
float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
|
||||
|
||||
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
|
||||
|
||||
const ::Plane* getPlanes() const { return _planes; }
|
||||
private:
|
||||
// camera location/orientation attributes
|
||||
glm::vec3 _position; // the position in world-frame
|
||||
glm::quat _orientation;
|
||||
glm::mat4 _view;
|
||||
|
||||
// Lens attributes
|
||||
void invalidate(); // causes all reasonable intersection tests to fail
|
||||
private:
|
||||
glm::mat4 _view;
|
||||
glm::mat4 _projection;
|
||||
|
||||
// calculated for orientation
|
||||
::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum
|
||||
|
||||
glm::vec3 _position; // position in world-frame
|
||||
glm::quat _orientation; // orientation in world-frame
|
||||
|
||||
// calculated from orientation
|
||||
glm::vec3 _direction = IDENTITY_FRONT;
|
||||
glm::vec3 _up = IDENTITY_UP;
|
||||
glm::vec3 _right = IDENTITY_RIGHT;
|
||||
|
||||
// calculated from projection
|
||||
glm::vec4 _corners[NUM_FRUSTUM_CORNERS];
|
||||
glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS];
|
||||
float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS;
|
||||
float _width { 1.0f };
|
||||
float _height { 1.0f };
|
||||
float _aspectRatio { 1.0f };
|
||||
float _focalLength { 0.25f };
|
||||
float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES };
|
||||
|
||||
// Calculated values
|
||||
glm::mat4 _inverseProjection;
|
||||
float _width = 1.0f;
|
||||
float _height = 1.0f;
|
||||
float _aspectRatio = 1.0f;
|
||||
float _nearClip = DEFAULT_NEAR_CLIP;
|
||||
float _farClip = DEFAULT_FAR_CLIP;
|
||||
float _focalLength = 0.25f;
|
||||
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
|
||||
glm::vec4 _corners[8];
|
||||
glm::vec3 _cornersWorld[8];
|
||||
::Plane _planes[6]; // plane normals point inside frustum
|
||||
float _nearClip { DEFAULT_NEAR_CLIP };
|
||||
float _farClip { DEFAULT_FAR_CLIP };
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
|
@ -177,6 +170,4 @@ private:
|
|||
};
|
||||
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
||||
|
||||
#endif // hifi_ViewFrustum_h
|
|
@ -12,13 +12,17 @@ if (APPLE)
|
|||
|
||||
set(TARGET_NAME oculusLegacy)
|
||||
setup_hifi_plugin()
|
||||
link_hifi_libraries(shared gl gpu plugins display-plugins input-plugins)
|
||||
link_hifi_libraries(shared gl gpu plugins ui display-plugins input-plugins)
|
||||
|
||||
include_hifi_library_headers(octree)
|
||||
|
||||
add_dependency_external_projects(LibOVR)
|
||||
find_package(LibOVR REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES} ${COCOA_LIBRARY} ${IOKIT_LIBRARY})
|
||||
|
||||
|
||||
|
||||
endif()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include <QtCore/QThread.h>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtOpenGL/QGLWidget>
|
||||
#include <GLMHelpers.h>
|
||||
|
@ -16,7 +17,12 @@
|
|||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QScreen>
|
||||
#include <gl/GLWindow.h>
|
||||
#include <gl/GLWidget.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
#include <MainWindow.h>
|
||||
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#include <PerfStat.h>
|
||||
#include <gl/OglplusHelpers.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
@ -39,7 +45,7 @@ void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
_trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime);
|
||||
_currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||
_currentRenderFrameInfo.rawRenderPose = _currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
}
|
||||
|
@ -72,14 +78,34 @@ bool OculusLegacyDisplayPlugin::isSupported() const {
|
|||
}
|
||||
|
||||
bool OculusLegacyDisplayPlugin::internalActivate() {
|
||||
Parent::internalActivate();
|
||||
|
||||
if (!Parent::internalActivate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(ovr_Initialize(nullptr))) {
|
||||
Q_ASSERT(false);
|
||||
qFatal("Failed to Initialize SDK");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
_hmdWindow = new GLWindow();
|
||||
_hmdWindow->create();
|
||||
_hmdWindow->createContext(_container->getPrimaryContext());
|
||||
auto hmdScreen = qApp->screens()[_hmdScreen];
|
||||
auto hmdGeometry = hmdScreen->geometry();
|
||||
_hmdWindow->setGeometry(hmdGeometry);
|
||||
_hmdWindow->showFullScreen();
|
||||
|
||||
_hmdWindow->makeCurrent();
|
||||
glClearColor(1, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
_hmdWindow->swapBuffers();
|
||||
|
||||
_container->makeRenderingContextCurrent();
|
||||
|
||||
QOpenGLContextWrapper(_hmdWindow->context()).moveToThread(_presentThread);
|
||||
|
||||
_hswDismissed = false;
|
||||
_hmd = ovrHmd_Create(0);
|
||||
if (!_hmd) {
|
||||
|
@ -96,7 +122,8 @@ bool OculusLegacyDisplayPlugin::internalActivate() {
|
|||
ovrMatrix4f ovrPerspectiveProjection =
|
||||
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
||||
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeViewOffset));
|
||||
_ovrEyeOffsets[eye] = erd.HmdToEyeViewOffset;
|
||||
_eyeOffsets[eye] = glm::translate(mat4(), -1.0f * toGlm(_ovrEyeOffsets[eye]));
|
||||
eyeSizes[eye] = toGlm(ovrHmd_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f));
|
||||
});
|
||||
|
||||
|
@ -121,6 +148,11 @@ void OculusLegacyDisplayPlugin::internalDeactivate() {
|
|||
ovrHmd_Destroy(_hmd);
|
||||
_hmd = nullptr;
|
||||
ovr_Shutdown();
|
||||
_hmdWindow->showNormal();
|
||||
_hmdWindow->destroy();
|
||||
_hmdWindow->deleteLater();
|
||||
_hmdWindow = nullptr;
|
||||
_container->makeRenderingContextCurrent();
|
||||
}
|
||||
|
||||
// DLL based display plugins MUST initialize GLEW inside the DLL code.
|
||||
|
@ -131,20 +163,21 @@ void OculusLegacyDisplayPlugin::customizeContext() {
|
|||
glewInit();
|
||||
glGetError();
|
||||
});
|
||||
_hmdWindow->requestActivate();
|
||||
QThread::msleep(1000);
|
||||
Parent::customizeContext();
|
||||
#if 0
|
||||
ovrGLConfig config; memset(&config, 0, sizeof(ovrRenderAPIConfig));
|
||||
auto& header = config.Config.Header;
|
||||
header.API = ovrRenderAPI_OpenGL;
|
||||
header.BackBufferSize = _hmd->Resolution;
|
||||
header.Multisample = 1;
|
||||
int distortionCaps = ovrDistortionCap_TimeWarp;
|
||||
int distortionCaps = ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette;
|
||||
|
||||
memset(_eyeTextures, 0, sizeof(ovrTexture) * 2);
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
auto& header = _eyeTextures[eye].Header;
|
||||
header.API = ovrRenderAPI_OpenGL;
|
||||
header.TextureSize = { (int)_desiredFramebufferSize.x, (int)_desiredFramebufferSize.y };
|
||||
header.TextureSize = { (int)_renderTargetSize.x, (int)_renderTargetSize.y };
|
||||
header.RenderViewport.Size = header.TextureSize;
|
||||
header.RenderViewport.Size.w /= 2;
|
||||
if (eye == ovrEye_Right) {
|
||||
|
@ -152,29 +185,57 @@ void OculusLegacyDisplayPlugin::customizeContext() {
|
|||
}
|
||||
});
|
||||
|
||||
if (_hmdWindow->makeCurrent()) {
|
||||
#ifndef NDEBUG
|
||||
ovrBool result =
|
||||
#endif
|
||||
ovrHmd_ConfigureRendering(_hmd, &config.Config, distortionCaps, _eyeFovs, _eyeRenderDescs);
|
||||
assert(result);
|
||||
ovrBool result =
|
||||
#endif
|
||||
ovrHmd_ConfigureRendering(_hmd, &config.Config, distortionCaps, _eyeFovs, _eyeRenderDescs);
|
||||
assert(result);
|
||||
_hmdWindow->doneCurrent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
void OculusLegacyDisplayPlugin::uncustomizeContext() {
|
||||
HmdDisplayPlugin::uncustomizeContext();
|
||||
_hmdWindow->doneCurrent();
|
||||
QOpenGLContextWrapper(_hmdWindow->context()).moveToThread(qApp->thread());
|
||||
Parent::uncustomizeContext();
|
||||
}
|
||||
|
||||
void OculusLegacyDisplayPlugin::internalPresent() {
|
||||
ovrHmd_BeginFrame(_hmd, 0);
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
reinterpret_cast<ovrGLTexture&>(_eyeTextures[eye]).OGL.TexId = _currentSceneTexture;
|
||||
});
|
||||
ovrHmd_EndFrame(_hmd, _eyePoses, _eyeTextures);
|
||||
}
|
||||
void OculusLegacyDisplayPlugin::hmdPresent() {
|
||||
if (!_hswDismissed) {
|
||||
ovrHSWDisplayState hswState;
|
||||
ovrHmd_GetHSWDisplayState(_hmd, &hswState);
|
||||
if (hswState.Displayed) {
|
||||
ovrHmd_DismissHSWDisplay(_hmd);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
auto r = glm::quat_cast(_currentPresentFrameInfo.presentPose);
|
||||
ovrQuatf ovrRotation = { r.x, r.y, r.z, r.w };
|
||||
ovrPosef eyePoses[2];
|
||||
memset(eyePoses, 0, sizeof(ovrPosef) * 2);
|
||||
eyePoses[0].Orientation = eyePoses[1].Orientation = ovrRotation;
|
||||
|
||||
GLint texture = oglplus::GetName(_compositeFramebuffer->color);
|
||||
auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
glFlush();
|
||||
if (_hmdWindow->makeCurrent()) {
|
||||
glClearColor(0, 0.4, 0.8, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ovrHmd_BeginFrame(_hmd, _currentPresentFrameIndex);
|
||||
glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(sync);
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
reinterpret_cast<ovrGLTexture&>(_eyeTextures[eye]).OGL.TexId = texture;
|
||||
});
|
||||
ovrHmd_EndFrame(_hmd, eyePoses, _eyeTextures);
|
||||
_hmdWindow->doneCurrent();
|
||||
}
|
||||
static auto widget = _container->getPrimaryWidget();
|
||||
widget->makeCurrent();
|
||||
}
|
||||
|
||||
int OculusLegacyDisplayPlugin::getHmdScreen() const {
|
||||
return _hmdScreen;
|
||||
|
@ -184,4 +245,3 @@ float OculusLegacyDisplayPlugin::getTargetFrameRate() const {
|
|||
return TARGET_RATE_OculusLegacy;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,42 +14,43 @@
|
|||
#include <OVR_CAPI.h>
|
||||
|
||||
const float TARGET_RATE_OculusLegacy = 75.0f;
|
||||
class GLWindow;
|
||||
|
||||
class OculusLegacyDisplayPlugin : public HmdDisplayPlugin {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
OculusLegacyDisplayPlugin();
|
||||
virtual bool isSupported() const override;
|
||||
virtual const QString& getName() const override { return NAME; }
|
||||
bool isSupported() const override;
|
||||
const QString& getName() const override { return NAME; }
|
||||
|
||||
virtual int getHmdScreen() const override;
|
||||
int getHmdScreen() const override;
|
||||
|
||||
// Stereo specific methods
|
||||
virtual void resetSensors() override;
|
||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||
void resetSensors() override;
|
||||
void beginFrameRender(uint32_t frameIndex) override;
|
||||
|
||||
virtual float getTargetFrameRate() const override;
|
||||
float getTargetFrameRate() const override;
|
||||
|
||||
protected:
|
||||
virtual bool internalActivate() override;
|
||||
virtual void internalDeactivate() override;
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
|
||||
virtual void customizeContext() override;
|
||||
void hmdPresent() override {}
|
||||
void customizeContext() override;
|
||||
void uncustomizeContext() override;
|
||||
void hmdPresent() override;
|
||||
bool isHmdMounted() const override { return true; }
|
||||
#if 0
|
||||
virtual void uncustomizeContext() override;
|
||||
virtual void internalPresent() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static const QString NAME;
|
||||
|
||||
GLWindow* _hmdWindow{ nullptr };
|
||||
ovrHmd _hmd;
|
||||
mutable ovrTrackingState _trackingState;
|
||||
ovrEyeRenderDesc _eyeRenderDescs[2];
|
||||
ovrVector3f _ovrEyeOffsets[2];
|
||||
|
||||
ovrFovPort _eyeFovs[2];
|
||||
//ovrTexture _eyeTextures[2]; // FIXME - not currently in use
|
||||
ovrTexture _eyeTextures[2]; // FIXME - not currently in use
|
||||
mutable int _hmdScreen { -1 };
|
||||
bool _hswDismissed { false };
|
||||
};
|
||||
|
|
|
@ -26,8 +26,8 @@ function getFrame(callback) {
|
|||
}
|
||||
|
||||
function makeFrame(state) {
|
||||
if (state == Resource.State.FAILED) { throw "Failed to load frame"; }
|
||||
if (state != Resource.State.FINISHED) { return; }
|
||||
if (state === Resource.State.FAILED) { throw "Failed to load frame"; }
|
||||
if (state !== Resource.State.FINISHED) { return; }
|
||||
|
||||
var pictureFrameProperties = {
|
||||
name: 'scriptableResourceTest Picture Frame',
|
||||
|
@ -50,7 +50,6 @@ function getFrame(callback) {
|
|||
position.x += - 5 * Math.sin(rads);
|
||||
position.z += - 5 * Math.cos(rads);
|
||||
|
||||
print(JSON.stringify(position));
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
@ -67,10 +66,10 @@ function prefetch(callback) {
|
|||
var filepath = MOVIE_URL + padded + '.jpg';
|
||||
var texture = TextureCache.prefetch(filepath);
|
||||
frames.push(texture);
|
||||
if (!texture.state == Resource.State.FINISHED) {
|
||||
if (texture.state !== Resource.State.FINISHED) {
|
||||
numLoading++;
|
||||
texture.stateChanged.connect(function(state) {
|
||||
if (state == Resource.State.FAILED || state == Resource.State.FINISHED) {
|
||||
if (state === Resource.State.FAILED || state === Resource.State.FINISHED) {
|
||||
--numLoading;
|
||||
if (!numLoading) { callback(frames); }
|
||||
}
|
||||
|
|
34
scripts/developer/tests/scriptableResource/loadPerfTest.js
Normal file
34
scripts/developer/tests/scriptableResource/loadPerfTest.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// loadPerfTest.js
|
||||
// scripts/developer/tests/scriptableResource
|
||||
//
|
||||
// Created by Zach Pomerantz on 4/27/16.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Preloads 158 textures 50 times for performance profiling.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var TIMES = 50;
|
||||
|
||||
Script.include([
|
||||
'../../../developer/utilities/cache/cacheStats.js',
|
||||
'lib.js',
|
||||
], function() {
|
||||
var fetch = function() {
|
||||
prefetch(function(frames) {
|
||||
while (frames.length) { frames.pop(); }
|
||||
Script.requestGarbageCollection();
|
||||
|
||||
if (--TIMES > 0) {
|
||||
// Pause a bit to avoid a deadlock
|
||||
var DEADLOCK_AVOIDANCE_TIMEOUT = 100;
|
||||
Script.setTimeout(fetch, DEADLOCK_AVOIDANCE_TIMEOUT);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
fetch();
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// testMovie.js
|
||||
// movieTest.js
|
||||
// scripts/developer/tests/scriptableResource
|
||||
//
|
||||
// Created by Zach Pomerantz on 4/27/16.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// testPrefetch.js
|
||||
// prefetchTest.js
|
||||
// scripts/developer/tests/scriptableResource
|
||||
//
|
||||
// Created by Zach Pomerantz on 4/27/16.
|
||||
|
|
|
@ -29,6 +29,10 @@ var IDENTITY_QUAT = {
|
|||
var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with handControllerGrab.js
|
||||
var GRAB_USER_DATA_KEY = "grabKey"; // shared with handControllerGrab.js
|
||||
|
||||
var MSECS_PER_SEC = 1000.0;
|
||||
var HEART_BEAT_INTERVAL = 5 * MSECS_PER_SEC;
|
||||
var HEART_BEAT_TIMEOUT = 15 * MSECS_PER_SEC;
|
||||
|
||||
var DEFAULT_GRABBABLE_DATA = {
|
||||
grabbable: true,
|
||||
invertSolidWhileHeld: false
|
||||
|
@ -335,6 +339,9 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
|
||||
mouse.startDrag(event);
|
||||
|
||||
var now = Date.now();
|
||||
this.lastHeartBeat = 0;
|
||||
|
||||
var clickedEntity = pickResults.entityID;
|
||||
var entityProperties = Entities.getEntityProperties(clickedEntity)
|
||||
this.startPosition = entityProperties.position;
|
||||
|
@ -376,7 +383,16 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
if(!entityIsGrabbedByOther(this.entityID)){
|
||||
this.moveEvent(event);
|
||||
}
|
||||
|
||||
|
||||
var args = "mouse";
|
||||
Entities.callEntityMethod(this.entityID, "startDistanceGrab", args);
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'grab',
|
||||
grabbedEntity: this.entityID
|
||||
}));
|
||||
|
||||
|
||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||
//Audio.playSound(grabSound, { position: entityProperties.position, volume: VOLUME });
|
||||
}
|
||||
|
@ -394,17 +410,41 @@ Grabber.prototype.releaseEvent = function(event) {
|
|||
|
||||
beacon.disable();
|
||||
|
||||
var args = "mouse";
|
||||
Entities.callEntityMethod(this.entityID, "releaseGrab", args);
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.entityID,
|
||||
joint: "mouse"
|
||||
}));
|
||||
|
||||
|
||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||
//Audio.playSound(releaseSound, { position: entityProperties.position, volume: VOLUME });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Grabber.prototype.heartBeat = function(entityID) {
|
||||
var now = Date.now();
|
||||
if (now - this.lastHeartBeat > HEART_BEAT_INTERVAL) {
|
||||
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
||||
data["heartBeat"] = now;
|
||||
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
|
||||
this.lastHeartBeat = now;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Grabber.prototype.moveEvent = function(event) {
|
||||
if (!this.isGrabbing) {
|
||||
return;
|
||||
}
|
||||
mouse.updateDrag(event);
|
||||
|
||||
this.heartBeat(this.entityID);
|
||||
|
||||
// see if something added/restored gravity
|
||||
var entityProperties = Entities.getEntityProperties(this.entityID);
|
||||
if (Vec3.length(entityProperties.gravity) != 0) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */
|
||||
|
||||
Script.include("../libraries/utils.js");
|
||||
Script.include("/~/system/libraries/utils.js");
|
||||
|
||||
|
||||
//
|
||||
|
@ -28,7 +28,7 @@ var WANT_DEBUG_SEARCH_NAME = null;
|
|||
|
||||
var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing
|
||||
var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab
|
||||
var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab
|
||||
var TRIGGER_GRAB_VALUE = 0.75; // Squeezed far enough to complete distant grab
|
||||
var TRIGGER_OFF_VALUE = 0.15;
|
||||
|
||||
var BUMPER_ON_VALUE = 0.5;
|
||||
|
@ -102,7 +102,6 @@ var ZERO_VEC = {
|
|||
};
|
||||
|
||||
var NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
|
||||
var MSEC_PER_SEC = 1000.0;
|
||||
|
||||
// these control how long an abandoned pointer line or action will hang around
|
||||
var LIFETIME = 10;
|
||||
|
@ -740,10 +739,6 @@ function MyController(hand) {
|
|||
};
|
||||
|
||||
this.propsArePhysical = function(props) {
|
||||
if (!props.dynamic && props.parentID != MyAvatar.sessionUUID) {
|
||||
// if we have parented something, don't do this check on dynamic.
|
||||
return false;
|
||||
}
|
||||
var isPhysical = (props.shapeType && props.shapeType != 'none');
|
||||
return isPhysical;
|
||||
}
|
||||
|
@ -837,7 +832,7 @@ function MyController(hand) {
|
|||
this.search = function() {
|
||||
this.grabbedEntity = null;
|
||||
this.isInitialGrab = false;
|
||||
this.doubleParentGrab = false;
|
||||
this.shouldResetParentOnRelease = false;
|
||||
|
||||
this.checkForStrayChildren();
|
||||
|
||||
|
@ -914,7 +909,7 @@ function MyController(hand) {
|
|||
candidateEntities = rayPickedCandidateEntities.concat(nearPickedCandidateEntities);
|
||||
|
||||
var forbiddenNames = ["Grab Debug Entity", "grab pointer"];
|
||||
var forbiddenTypes = ['Unknown', 'Light', 'ParticleEffect', 'PolyLine', 'Zone'];
|
||||
var forbiddenTypes = ['Unknown', 'Light', 'PolyLine', 'Zone'];
|
||||
|
||||
var minDistance = PICK_MAX_DISTANCE;
|
||||
var i, props, distance, grabbableData;
|
||||
|
@ -1019,6 +1014,10 @@ function MyController(hand) {
|
|||
if (this.state == STATE_SEARCHING) {
|
||||
this.setState(STATE_NEAR_GRABBING);
|
||||
} else { // (this.state == STATE_HOLD_SEARCHING)
|
||||
// if there was already an action, we'll need to set the parent back to null once we release
|
||||
this.shouldResetParentOnRelease = true;
|
||||
this.previousParentID = props.parentID;
|
||||
this.previousParentJointIndex = props.parentJointIndex;
|
||||
this.setState(STATE_HOLD);
|
||||
}
|
||||
return;
|
||||
|
@ -1064,7 +1063,7 @@ function MyController(hand) {
|
|||
// it's not physical and it's already held via parenting. go ahead and grab it, but
|
||||
// save off the current parent and joint. this wont always be right if there are more than
|
||||
// two grabs and the order of release isn't opposite of the order of grabs.
|
||||
this.doubleParentGrab = true;
|
||||
this.shouldResetParentOnRelease = true;
|
||||
this.previousParentID = props.parentID;
|
||||
this.previousParentJointIndex = props.parentJointIndex;
|
||||
if (this.state == STATE_SEARCHING) {
|
||||
|
@ -1149,7 +1148,7 @@ function MyController(hand) {
|
|||
if (this.actionID === NULL_UUID) {
|
||||
this.actionID = null;
|
||||
}
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||
|
||||
if (this.actionID !== null) {
|
||||
this.setState(STATE_CONTINUE_DISTANCE_HOLDING);
|
||||
|
@ -1184,7 +1183,7 @@ function MyController(hand) {
|
|||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||
|
||||
var now = Date.now();
|
||||
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
|
||||
var deltaTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds
|
||||
this.currentObjectTime = now;
|
||||
|
||||
// the action was set up when this.distanceHolding was called. update the targets.
|
||||
|
@ -1302,7 +1301,7 @@ function MyController(hand) {
|
|||
ttl: ACTION_TTL
|
||||
});
|
||||
if (success) {
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||
} else {
|
||||
print("continueDistanceHolding -- updateAction failed");
|
||||
}
|
||||
|
@ -1327,7 +1326,7 @@ function MyController(hand) {
|
|||
return false;
|
||||
}
|
||||
var now = Date.now();
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -1436,6 +1435,10 @@ function MyController(hand) {
|
|||
if (!this.setupHoldAction()) {
|
||||
return;
|
||||
}
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'grab',
|
||||
grabbedEntity: this.grabbedEntity
|
||||
}));
|
||||
} else {
|
||||
// grab entity via parenting
|
||||
this.actionID = null;
|
||||
|
@ -1563,7 +1566,7 @@ function MyController(hand) {
|
|||
var now = Date.now();
|
||||
|
||||
var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters
|
||||
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
|
||||
var deltaTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds
|
||||
|
||||
if (deltaTime > 0.0) {
|
||||
var worldDeltaPosition = Vec3.subtract(props.position, this.currentObjectPosition);
|
||||
|
@ -1590,7 +1593,7 @@ function MyController(hand) {
|
|||
this.callEntityMethodOnGrabbed("continueNearGrab");
|
||||
}
|
||||
|
||||
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
|
||||
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSECS_PER_SEC) {
|
||||
// if less than a 5 seconds left, refresh the actions ttl
|
||||
var success = Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||
|
@ -1603,7 +1606,7 @@ function MyController(hand) {
|
|||
ignoreIK: this.ignoreIK
|
||||
});
|
||||
if (success) {
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||
} else {
|
||||
print("continueNearGrabbing -- updateAction failed");
|
||||
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||
|
@ -1838,12 +1841,12 @@ function MyController(hand) {
|
|||
|
||||
// things that are held by parenting and dropped with no velocity will end up as "static" in bullet. If
|
||||
// it looks like the dropped thing should fall, give it a little velocity.
|
||||
var props = Entities.getEntityProperties(entityID, ["parentID", "velocity"])
|
||||
var props = Entities.getEntityProperties(entityID, ["parentID", "velocity", "dynamic", "shapeType"])
|
||||
var parentID = props.parentID;
|
||||
var forceVelocity = false;
|
||||
|
||||
var doSetVelocity = false;
|
||||
if (parentID != NULL_UUID && deactiveProps.parentID == NULL_UUID) {
|
||||
if (parentID != NULL_UUID && deactiveProps.parentID == NULL_UUID && this.propsArePhysical(props)) {
|
||||
// TODO: EntityScriptingInterface::convertLocationToScriptSemantics should be setting up
|
||||
// props.velocity to be a world-frame velocity and localVelocity to be vs parent. Until that
|
||||
// is done, we use a measured velocity here so that things held via a bumper-grab / parenting-grab
|
||||
|
@ -1881,7 +1884,7 @@ function MyController(hand) {
|
|||
}
|
||||
|
||||
data = null;
|
||||
} else if (this.doubleParentGrab) {
|
||||
} else if (this.shouldResetParentOnRelease) {
|
||||
// we parent-grabbed this from another parent grab. try to put it back where we found it.
|
||||
var deactiveProps = {
|
||||
parentID: this.previousParentID,
|
||||
|
@ -1892,7 +1895,8 @@ function MyController(hand) {
|
|||
Entities.editEntity(entityID, deactiveProps);
|
||||
} else if (noVelocity) {
|
||||
Entities.editEntity(entityID, {velocity: {x: 0.0, y: 0.0, z: 0.0},
|
||||
angularVelocity: {x: 0.0, y: 0.0, z: 0.0}});
|
||||
angularVelocity: {x: 0.0, y: 0.0, z: 0.0},
|
||||
dynamic: data["dynamic"]});
|
||||
}
|
||||
} else {
|
||||
data = null;
|
||||
|
|
181
scripts/tutorials/NBody/gravity.js
Normal file
181
scripts/tutorials/NBody/gravity.js
Normal file
|
@ -0,0 +1,181 @@
|
|||
// gravity.js
|
||||
//
|
||||
// Created by Philip Rosedale on March 29, 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// This entity script causes the object to move with gravitational force and be attracted to other spheres nearby.
|
||||
// The force is scaled by GRAVITY_STRENGTH, and only entities of type "Sphere" within GRAVITY_RANGE will affect it.
|
||||
// The person who has most recently grabbed this object will simulate it.
|
||||
//
|
||||
|
||||
function Timer() {
|
||||
var time;
|
||||
var count = 0;
|
||||
var totalTime = 0;
|
||||
this.reset = function() {
|
||||
count = 0;
|
||||
totalTime = 0;
|
||||
}
|
||||
this.start = function() {
|
||||
time = new Date().getTime();
|
||||
}
|
||||
this.record = function() {
|
||||
var elapsed = new Date().getTime() - time;
|
||||
totalTime += elapsed;
|
||||
count++;
|
||||
return elapsed;
|
||||
}
|
||||
this.count = function() {
|
||||
return count;
|
||||
}
|
||||
this.average = function() {
|
||||
return (count == 0) ? 0 : totalTime / count;
|
||||
}
|
||||
this.elapsed = function() {
|
||||
return new Date().getTime() - time;
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
var entityID,
|
||||
wantDebug = true,
|
||||
CHECK_INTERVAL = 10.00,
|
||||
SEARCH_INTERVAL = 1000,
|
||||
GRAVITY_RANGE = 20.0,
|
||||
GRAVITY_STRENGTH = 1.0,
|
||||
MIN_VELOCITY = 0.01,
|
||||
timeoutID = null,
|
||||
timeSinceLastSearch = 0,
|
||||
timer = new Timer(),
|
||||
simulate = false,
|
||||
spheres = [];
|
||||
|
||||
var printDebug = function(message) {
|
||||
if (wantDebug) {
|
||||
print(message);
|
||||
}
|
||||
}
|
||||
|
||||
var greatestDimension = function(dimensions) {
|
||||
return Math.max(Math.max(dimensions.x, dimensions.y), dimensions.z);
|
||||
}
|
||||
|
||||
var mass2 = function(dimensions) {
|
||||
return dimensions.x * dimensions.y * dimensions.z;
|
||||
}
|
||||
|
||||
var findSpheres = function(position) {
|
||||
var entities = Entities.findEntities(position, GRAVITY_RANGE);
|
||||
spheres = [];
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
if (entityID == spheres[i]) {
|
||||
// this entity doesn't experience its own gravity.
|
||||
continue;
|
||||
}
|
||||
var props = Entities.getEntityProperties(entities[i]);
|
||||
if (props && (props.shapeType == "sphere" || props.type == "Sphere")) {
|
||||
spheres.push(entities[i]);
|
||||
}
|
||||
}
|
||||
// print("FOUND " + spheres.length + " SPHERES");
|
||||
}
|
||||
|
||||
var applyGravity = function() {
|
||||
if (!simulate) {
|
||||
return;
|
||||
}
|
||||
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
if (!properties || !properties.position) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update the list of nearby spheres
|
||||
var deltaTime = timer.elapsed() / 1000.0;
|
||||
if (deltaTime == 0.0) {
|
||||
return;
|
||||
}
|
||||
timeSinceLastSearch += CHECK_INTERVAL;
|
||||
if (timeSinceLastSearch >= SEARCH_INTERVAL) {
|
||||
findSpheres(properties.position);
|
||||
timeSinceLastSearch = 0;
|
||||
}
|
||||
|
||||
var deltaVelocity = { x: 0, y: 0, z: 0 };
|
||||
var otherCount = 0;
|
||||
var mass = mass2(properties.dimensions);
|
||||
|
||||
for (var i = 0; i < spheres.length; i++) {
|
||||
otherProperties = Entities.getEntityProperties(spheres[i]);
|
||||
if (!otherProperties || !otherProperties.position) {
|
||||
continue; // sphere was deleted
|
||||
}
|
||||
otherCount++;
|
||||
var radius = Vec3.distance(properties.position, otherProperties.position);
|
||||
var otherMass = mass2(otherProperties.dimensions);
|
||||
var r = (greatestDimension(properties.dimensions) + greatestDimension(otherProperties.dimensions)) / 2;
|
||||
if (radius > r) {
|
||||
var n0 = Vec3.normalize(Vec3.subtract(otherProperties.position, properties.position));
|
||||
var n1 = Vec3.multiply(deltaTime * GRAVITY_STRENGTH * otherMass / (radius * radius), n0);
|
||||
deltaVelocity = Vec3.sum(deltaVelocity, n1);
|
||||
}
|
||||
}
|
||||
Entities.editEntity(entityID, { velocity: Vec3.sum(properties.velocity, deltaVelocity) });
|
||||
if (Vec3.length(properties.velocity) < MIN_VELOCITY) {
|
||||
print("Gravity simulation stopped due to velocity");
|
||||
simulate = false;
|
||||
} else {
|
||||
timer.start();
|
||||
timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL);
|
||||
}
|
||||
}
|
||||
this.applyGravity = applyGravity;
|
||||
|
||||
var releaseGrab = function() {
|
||||
printDebug("Gravity simulation started.");
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
findSpheres(properties.position);
|
||||
timer.start();
|
||||
timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL);
|
||||
simulate = true;
|
||||
}
|
||||
this.releaseGrab = releaseGrab;
|
||||
|
||||
var preload = function (givenEntityID) {
|
||||
printDebug("load gravity...");
|
||||
entityID = givenEntityID;
|
||||
};
|
||||
this.preload = preload;
|
||||
|
||||
var unload = function () {
|
||||
printDebug("Unload gravity...");
|
||||
if (timeoutID !== undefined) {
|
||||
Script.clearTimeout(timeoutID);
|
||||
}
|
||||
if (simulate) {
|
||||
Entities.editEntity(entityID, { velocity: { x: 0, y: 0, z: 0 } });
|
||||
}
|
||||
};
|
||||
this.unload = unload;
|
||||
|
||||
var handleMessages = function(channel, message, sender) {
|
||||
if (channel === 'Hifi-Object-Manipulation') {
|
||||
try {
|
||||
var parsedMessage = JSON.parse(message);
|
||||
if (parsedMessage.action === 'grab' && parsedMessage.grabbedEntity == entityID) {
|
||||
print("Gravity simulation stopped due to grab");
|
||||
simulate = false;
|
||||
}
|
||||
} catch (e) {
|
||||
print('error parsing Hifi-Object-Manipulation message: ' + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.handleMessages = handleMessages;
|
||||
|
||||
Messages.messageReceived.connect(this.handleMessages);
|
||||
Messages.subscribe('Hifi-Object-Manipulation');
|
||||
});
|
72
scripts/tutorials/NBody/gravity.svg
Normal file
72
scripts/tutorials/NBody/gravity.svg
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64.000001 64.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="gravity.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="192.07838"
|
||||
inkscape:cy="33.619203"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="2782"
|
||||
inkscape:window-height="1764"
|
||||
inkscape:window-x="98"
|
||||
inkscape:window-y="36"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-988.36216)">
|
||||
<ellipse
|
||||
style="fill:#a09898;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4690"
|
||||
cx="12.142858"
|
||||
cy="1039.1478"
|
||||
rx="8.5714283"
|
||||
ry="8.2142859" />
|
||||
<ellipse
|
||||
style="fill:#3131d9;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4692"
|
||||
cx="39.285717"
|
||||
cy="1014.1478"
|
||||
rx="21.358366"
|
||||
ry="21.001223" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
166
scripts/tutorials/NBody/makePlanets.js
Normal file
166
scripts/tutorials/NBody/makePlanets.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
// makePlanets.js
|
||||
//
|
||||
// Created by Philip Rosedale on March 29, 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// Make an earth and moon, where you can grab and throw moon into orbit. Entity
|
||||
// script attached to moon gives it gravitation behavior and will also make it attracted to
|
||||
// other spheres placed nearby.
|
||||
//
|
||||
|
||||
var SCALE = 3.0;
|
||||
var EARTH_SIZE = 3.959 / SCALE;
|
||||
var MOON_SIZE = 1.079 / SCALE;
|
||||
|
||||
var BUTTON_SIZE = 32;
|
||||
var PADDING = 3;
|
||||
|
||||
var earth = null;
|
||||
var moon = null;
|
||||
|
||||
var SCRIPT_URL = Script.resolvePath("gravity.js");
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
Script.include(["/~/system/libraries/toolBars.js"]);
|
||||
var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.makePlanets.js");
|
||||
|
||||
var makePlanetsIconURL = Script.resolvePath("gravity.svg");
|
||||
var button = toolBar.addOverlay("image", {
|
||||
width: BUTTON_SIZE,
|
||||
height: BUTTON_SIZE,
|
||||
imageURL: makePlanetsIconURL,
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
var deleteButton = toolBar.addOverlay("image", {
|
||||
width: BUTTON_SIZE,
|
||||
height: BUTTON_SIZE,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png",
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
function inFrontOfMe(distance) {
|
||||
return Vec3.sum(Camera.getPosition(), Vec3.multiply(distance, Quat.getFront(Camera.getOrientation())));
|
||||
}
|
||||
|
||||
function onButtonClick() {
|
||||
earth = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "Earth",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/earth.fbx",
|
||||
position: inFrontOfMe(2 * EARTH_SIZE),
|
||||
dimensions: { x: EARTH_SIZE, y: EARTH_SIZE, z: EARTH_SIZE },
|
||||
shapeType: "sphere",
|
||||
lifetime: 86400, // 1 day
|
||||
angularDamping: 0,
|
||||
angularVelocity: { x: 0, y: 0.1, z: 0 },
|
||||
});
|
||||
moon = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "Moon",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/moon.fbx",
|
||||
position: inFrontOfMe(EARTH_SIZE - MOON_SIZE),
|
||||
dimensions: { x: MOON_SIZE, y: MOON_SIZE, z: MOON_SIZE },
|
||||
dynamic: true,
|
||||
damping: 0, // 0.01,
|
||||
angularDamping: 0, // 0.01,
|
||||
script: SCRIPT_URL,
|
||||
shapeType: "sphere"
|
||||
});
|
||||
Entities.addEntity({
|
||||
"accelerationSpread": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"alpha": 1,
|
||||
"alphaFinish": 0,
|
||||
"alphaStart": 1,
|
||||
"azimuthFinish": 0,
|
||||
"azimuthStart": 0,
|
||||
"color": {
|
||||
"blue": 255,
|
||||
"green": 255,
|
||||
"red": 255
|
||||
},
|
||||
"colorFinish": {
|
||||
"blue": 255,
|
||||
"green": 255,
|
||||
"red": 255
|
||||
},
|
||||
"colorStart": {
|
||||
"blue": 255,
|
||||
"green": 255,
|
||||
"red": 255
|
||||
},
|
||||
"dimensions": {
|
||||
"x": 0.10890001058578491,
|
||||
"y": 0.10890001058578491,
|
||||
"z": 0.10890001058578491
|
||||
},
|
||||
"emitAcceleration": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"emitOrientation": {
|
||||
"w": 0.99999994039535522,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"emitRate": 300,
|
||||
"emitSpeed": 0,
|
||||
"emitterShouldTrail": 1,
|
||||
"maxParticles": 10000,
|
||||
"name": "moon trail",
|
||||
"parentID": moon,
|
||||
"particleRadius": 0.005,
|
||||
"radiusFinish": 0.005,
|
||||
"radiusSpread": 0.005,
|
||||
"radiusStart": 0.005,
|
||||
"speedSpread": 0,
|
||||
"lifespan": 20,
|
||||
"textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
|
||||
"type": "ParticleEffect",
|
||||
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||
});
|
||||
}
|
||||
|
||||
function onDeleteButton() {
|
||||
Entities.deleteEntity(earth);
|
||||
Entities.deleteEntity(moon);
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var clickedText = false;
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||
x: event.x,
|
||||
y: event.y
|
||||
});
|
||||
if (clickedOverlay == button) {
|
||||
onButtonClick();
|
||||
} else if (clickedOverlay == deleteButton) {
|
||||
onDeleteButton();
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
toolBar.cleanup();
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -7,6 +7,6 @@ setup_hifi_project(Network Script)
|
|||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
||||
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(entities avatars shared octree gpu model fbx networking animation)
|
||||
link_hifi_libraries(entities avatars shared octree gpu model fbx networking animation audio)
|
||||
|
||||
package_libraries_for_deployment()
|
||||
|
|
Loading…
Reference in a new issue