mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 08:24:21 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
7178147535
13 changed files with 292 additions and 63 deletions
|
@ -57,6 +57,7 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "devices/LeapManager.h"
|
#include "devices/LeapManager.h"
|
||||||
#include "devices/OculusManager.h"
|
#include "devices/OculusManager.h"
|
||||||
|
#include "devices/TV3DManager.h"
|
||||||
#include "renderer/ProgramObject.h"
|
#include "renderer/ProgramObject.h"
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
#include "InfoView.h"
|
#include "InfoView.h"
|
||||||
|
@ -439,7 +440,10 @@ void Application::paintGL() {
|
||||||
|
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
OculusManager::display(whichCamera);
|
OculusManager::display(whichCamera);
|
||||||
|
} else if (TV3DManager::isConnected()) {
|
||||||
|
_glowEffect.prepare();
|
||||||
|
TV3DManager::display(whichCamera);
|
||||||
|
_glowEffect.render();
|
||||||
} else {
|
} else {
|
||||||
_glowEffect.prepare();
|
_glowEffect.prepare();
|
||||||
|
|
||||||
|
@ -474,8 +478,10 @@ void Application::paintGL() {
|
||||||
_mirrorCamera.update(1.0f/_fps);
|
_mirrorCamera.update(1.0f/_fps);
|
||||||
|
|
||||||
// set the bounds of rear mirror view
|
// set the bounds of rear mirror view
|
||||||
glViewport(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(), _mirrorViewRect.width(), _mirrorViewRect.height());
|
glViewport(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(),
|
||||||
glScissor(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(), _mirrorViewRect.width(), _mirrorViewRect.height());
|
_mirrorViewRect.width(), _mirrorViewRect.height());
|
||||||
|
glScissor(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(),
|
||||||
|
_mirrorViewRect.width(), _mirrorViewRect.height());
|
||||||
bool updateViewFrustum = false;
|
bool updateViewFrustum = false;
|
||||||
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
|
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
@ -506,7 +512,6 @@ void Application::paintGL() {
|
||||||
// restore absolute translations
|
// restore absolute translations
|
||||||
_myAvatar.getSkeletonModel().setTranslation(absoluteSkeletonTranslation);
|
_myAvatar.getSkeletonModel().setTranslation(absoluteSkeletonTranslation);
|
||||||
_myAvatar.getHead().getFaceModel().setTranslation(absoluteFaceTranslation);
|
_myAvatar.getHead().getFaceModel().setTranslation(absoluteFaceTranslation);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
displaySide(_mirrorCamera, true);
|
displaySide(_mirrorCamera, true);
|
||||||
}
|
}
|
||||||
|
@ -531,7 +536,8 @@ void Application::paintGL() {
|
||||||
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
|
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
OculusManager::configureCamera(camera, width, height);
|
OculusManager::configureCamera(camera, width, height);
|
||||||
|
} else if (TV3DManager::isConnected()) {
|
||||||
|
TV3DManager::configureCamera(camera, width, height);
|
||||||
} else {
|
} else {
|
||||||
camera.setAspectRatio((float)width / height);
|
camera.setAspectRatio((float)width / height);
|
||||||
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
|
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
|
||||||
|
@ -910,7 +916,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
case Qt::Key_J:
|
case Qt::Key_J:
|
||||||
if (isShifted) {
|
if (isShifted) {
|
||||||
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
|
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
|
||||||
|
if (TV3DManager::isConnected()) {
|
||||||
|
TV3DManager::configureCamera(_myCamera, _glWidget->width(),_glWidget->height());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
|
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
|
||||||
}
|
}
|
||||||
|
@ -920,6 +928,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
case Qt::Key_M:
|
case Qt::Key_M:
|
||||||
if (isShifted) {
|
if (isShifted) {
|
||||||
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
|
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
|
||||||
|
if (TV3DManager::isConnected()) {
|
||||||
|
TV3DManager::configureCamera(_myCamera, _glWidget->width(),_glWidget->height());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
|
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
|
||||||
|
@ -1839,6 +1850,13 @@ void Application::init() {
|
||||||
"trigger",
|
"trigger",
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TV3DManager::connect();
|
||||||
|
if (TV3DManager::isConnected()) {
|
||||||
|
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen),
|
||||||
|
"trigger",
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
LeapManager::initialize();
|
LeapManager::initialize();
|
||||||
|
|
||||||
|
@ -2426,7 +2444,7 @@ void Application::updateCamera(float deltaTime) {
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
|
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
|
||||||
|
|
||||||
if (!OculusManager::isConnected()) {
|
if (!OculusManager::isConnected() && !TV3DManager::isConnected()) {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||||
_myCamera.setMode(CAMERA_MODE_MIRROR);
|
_myCamera.setMode(CAMERA_MODE_MIRROR);
|
||||||
|
@ -3811,7 +3829,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... Avatars...");
|
"Application::renderAvatars()");
|
||||||
|
|
||||||
if (!selfAvatarOnly) {
|
if (!selfAvatarOnly) {
|
||||||
// Render avatars of other nodes
|
// Render avatars of other nodes
|
||||||
|
@ -4100,7 +4118,7 @@ void Application::resetSensors() {
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
OculusManager::reset();
|
OculusManager::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
QCursor::setPos(_headMouseX, _headMouseY);
|
QCursor::setPos(_headMouseX, _headMouseY);
|
||||||
_myAvatar.reset();
|
_myAvatar.reset();
|
||||||
_myTransmitter.resetLevels();
|
_myTransmitter.resetLevels();
|
||||||
|
|
|
@ -254,7 +254,6 @@ private slots:
|
||||||
void shrinkMirrorView();
|
void shrinkMirrorView();
|
||||||
void resetSensors();
|
void resetSensors();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
|
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
|
||||||
void updateProjectionMatrix();
|
void updateProjectionMatrix();
|
||||||
|
|
|
@ -232,6 +232,8 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true);
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H);
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H);
|
||||||
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0, false);
|
||||||
|
|
||||||
|
|
||||||
QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size");
|
QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size");
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,7 @@ namespace MenuOption {
|
||||||
const QString FilterSixense = "Smooth Sixense Movement";
|
const QString FilterSixense = "Smooth Sixense Movement";
|
||||||
const QString DontRenderVoxels = "Don't call _voxels.render()";
|
const QString DontRenderVoxels = "Don't call _voxels.render()";
|
||||||
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
|
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
|
||||||
|
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||||
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
||||||
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
|
|
|
@ -127,12 +127,12 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
||||||
//printf(">>>>>>> caught... handID:%d particle ID:%d _toyBallInHand[handID] = true\n", handID, closestParticle->getID());
|
//printf(">>>>>>> caught... handID:%d particle ID:%d _toyBallInHand[handID] = true\n", handID, closestParticle->getID());
|
||||||
_ballParticleEditHandles[handID] = caughtParticle;
|
_ballParticleEditHandles[handID] = caughtParticle;
|
||||||
caughtParticle = NULL;
|
caughtParticle = NULL;
|
||||||
// Play a catch sound!
|
|
||||||
|
// set the position of the catch sound to the new position of the ball
|
||||||
_catchInjector.setPosition(targetPosition);
|
_catchInjector.setPosition(targetPosition);
|
||||||
|
|
||||||
// inject the catch sound to the mixer and play it locally
|
// inject the catch sound to the mixer and play it locally
|
||||||
_catchInjector.injectViaThread(app->getAudio());
|
_catchInjector.injectViaThread(app->getAudio());
|
||||||
app->getAudio()->startDrumSound(1.0, 300, 0.75, 0.015);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
132
interface/src/devices/TV3DManager.cpp
Normal file
132
interface/src/devices/TV3DManager.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
//
|
||||||
|
// TV3DManager.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/24/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QOpenGLFramebufferObject>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
#include "TV3DManager.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
|
int TV3DManager::_screenWidth = 1;
|
||||||
|
int TV3DManager::_screenHeight = 1;
|
||||||
|
double TV3DManager::_aspect = 1.0;
|
||||||
|
eyeFrustum TV3DManager::_leftEye;
|
||||||
|
eyeFrustum TV3DManager::_rightEye;
|
||||||
|
|
||||||
|
|
||||||
|
bool TV3DManager::isConnected() {
|
||||||
|
return Menu::getInstance()->isOptionChecked(MenuOption::Enable3DTVMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TV3DManager::connect() {
|
||||||
|
Application* app = Application::getInstance();
|
||||||
|
int width = app->getGLWidget()->width();
|
||||||
|
int height = app->getGLWidget()->height();
|
||||||
|
Camera& camera = *app->getCamera();
|
||||||
|
|
||||||
|
configureCamera(camera, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The basic strategy of this stereoscopic rendering is explained here:
|
||||||
|
// http://www.orthostereo.com/geometryopengl.html
|
||||||
|
void TV3DManager::setFrustum(Camera& whichCamera) {
|
||||||
|
const double DTR = 0.0174532925; // degree to radians
|
||||||
|
const double IOD = 0.05; //intraocular distance
|
||||||
|
double fovy = whichCamera.getFieldOfView(); // field of view in y-axis
|
||||||
|
double nearZ = whichCamera.getNearClip(); // near clipping plane
|
||||||
|
double screenZ = Application::getInstance()->getViewFrustum()->getFocalLength(); // screen projection plane
|
||||||
|
|
||||||
|
double top = nearZ * tan(DTR * fovy / 2); //sets top of frustum based on fovy and near clipping plane
|
||||||
|
double right = _aspect * top; // sets right of frustum based on aspect ratio
|
||||||
|
double frustumshift = (IOD / 2) * nearZ / screenZ;
|
||||||
|
|
||||||
|
_leftEye.top = top;
|
||||||
|
_leftEye.bottom = -top;
|
||||||
|
_leftEye.left = -right + frustumshift;
|
||||||
|
_leftEye.right = right + frustumshift;
|
||||||
|
_leftEye.modelTranslation = IOD / 2;
|
||||||
|
|
||||||
|
_rightEye.top = top;
|
||||||
|
_rightEye.bottom = -top;
|
||||||
|
_rightEye.left = -right - frustumshift;
|
||||||
|
_rightEye.right = right - frustumshift;
|
||||||
|
_rightEye.modelTranslation = -IOD / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int screenHeight) {
|
||||||
|
if (screenHeight == 0) {
|
||||||
|
screenHeight = 1; // prevent divide by 0
|
||||||
|
}
|
||||||
|
_screenWidth = screenWidth;
|
||||||
|
_screenHeight = screenHeight;
|
||||||
|
_aspect= (double)_screenWidth / (double)_screenHeight;
|
||||||
|
setFrustum(whichCamera);
|
||||||
|
|
||||||
|
glViewport (0, 0, _screenWidth, _screenHeight); // sets drawing viewport
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TV3DManager::display(Camera& whichCamera) {
|
||||||
|
double nearZ = whichCamera.getNearClip(); // near clipping plane
|
||||||
|
double farZ = whichCamera.getFarClip(); // far clipping plane
|
||||||
|
|
||||||
|
// left eye portal
|
||||||
|
int portalX = 0;
|
||||||
|
int portalY = 0;
|
||||||
|
int portalW = Application::getInstance()->getGLWidget()->width() / 2;
|
||||||
|
int portalH = Application::getInstance()->getGLWidget()->height();
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
// render left side view
|
||||||
|
glViewport(portalX, portalY, portalW, portalH);
|
||||||
|
glScissor(portalX, portalY, portalW, portalH);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
{
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity(); // reset projection matrix
|
||||||
|
glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
|
||||||
|
glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
Application::getInstance()->displaySide(whichCamera);
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// render right side view
|
||||||
|
portalX = Application::getInstance()->getGLWidget()->width() / 2;
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
// render left side view
|
||||||
|
glViewport(portalX, portalY, portalW, portalH);
|
||||||
|
glScissor(portalX, portalY, portalW, portalH);
|
||||||
|
glPushMatrix();
|
||||||
|
{
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity(); // reset projection matrix
|
||||||
|
glFrustum(_rightEye.left, _rightEye.right, _rightEye.bottom, _rightEye.top, nearZ, farZ); // set left view frustum
|
||||||
|
glTranslatef(_rightEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
Application::getInstance()->displaySide(whichCamera);
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// reset the viewport to how we started
|
||||||
|
glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height());
|
||||||
|
}
|
41
interface/src/devices/TV3DManager.h
Normal file
41
interface/src/devices/TV3DManager.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// TV3DManager.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/24/2013
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__TV3DManager__
|
||||||
|
#define __hifi__TV3DManager__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Camera;
|
||||||
|
|
||||||
|
struct eyeFrustum {
|
||||||
|
double left;
|
||||||
|
double right;
|
||||||
|
double bottom;
|
||||||
|
double top;
|
||||||
|
float modelTranslation;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Handles interaction with 3D TVs
|
||||||
|
class TV3DManager {
|
||||||
|
public:
|
||||||
|
static void connect();
|
||||||
|
static bool isConnected();
|
||||||
|
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
|
||||||
|
static void display(Camera& whichCamera);
|
||||||
|
private:
|
||||||
|
static void setFrustum(Camera& whichCamera);
|
||||||
|
static int _screenWidth;
|
||||||
|
static int _screenHeight;
|
||||||
|
static double _aspect;
|
||||||
|
static eyeFrustum _leftEye;
|
||||||
|
static eyeFrustum _rightEye;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__TV3DManager__) */
|
|
@ -41,6 +41,8 @@ enum KeyState
|
||||||
DELETE_KEY_DOWN
|
DELETE_KEY_DOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const glm::vec3 vec3Zero(0.0f);
|
||||||
|
|
||||||
class JointData;
|
class JointData;
|
||||||
|
|
||||||
class AvatarData : public NodeData {
|
class AvatarData : public NodeData {
|
||||||
|
@ -103,6 +105,17 @@ public:
|
||||||
|
|
||||||
void setHeadData(HeadData* headData) { _headData = headData; }
|
void setHeadData(HeadData* headData) { _headData = headData; }
|
||||||
void setHandData(HandData* handData) { _handData = handData; }
|
void setHandData(HandData* handData) { _handData = handData; }
|
||||||
|
|
||||||
|
virtual const glm::vec3& getVelocity() const { return vec3Zero; }
|
||||||
|
|
||||||
|
/// Checks for penetration between the described sphere and the avatar.
|
||||||
|
/// \param penetratorCenter the center of the penetration test sphere
|
||||||
|
/// \param penetratorRadius the radius of the penetration test sphere
|
||||||
|
/// \param penetration[out] the vector in which to store the penetration
|
||||||
|
/// \param skeletonSkipIndex if not -1, the index of a joint to skip (along with its descendents) in the skeleton model
|
||||||
|
/// \return whether or not the sphere penetrated
|
||||||
|
virtual bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||||
|
glm::vec3& penetration, int skeletonSkipIndex = -1) { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
|
|
|
@ -572,7 +572,7 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
|
||||||
|
|
||||||
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
OctreeElement*& node, float& distance, BoxFace& face) {
|
OctreeElement*& node, float& distance, BoxFace& face) {
|
||||||
RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance, face };
|
RayArgs args = { origin / static_cast<float>(TREE_SCALE), direction, node, distance, face };
|
||||||
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
||||||
return args.found;
|
return args.found;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +600,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
||||||
if (element->hasContent()) {
|
if (element->hasContent()) {
|
||||||
glm::vec3 elementPenetration;
|
glm::vec3 elementPenetration;
|
||||||
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
|
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
|
||||||
args->penetration = addPenetrations(args->penetration, elementPenetration * (float)TREE_SCALE);
|
args->penetration = addPenetrations(args->penetration, elementPenetration * static_cast<float>(TREE_SCALE));
|
||||||
args->found = true;
|
args->found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,7 +610,12 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
||||||
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
||||||
void** penetratedObject) {
|
void** penetratedObject) {
|
||||||
|
|
||||||
SphereArgs args = { center / (float)TREE_SCALE, radius / TREE_SCALE, penetration, false, NULL };
|
SphereArgs args = {
|
||||||
|
center / static_cast<float>(TREE_SCALE),
|
||||||
|
radius / static_cast<float>(TREE_SCALE),
|
||||||
|
penetration,
|
||||||
|
false,
|
||||||
|
NULL };
|
||||||
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
recurseTreeWithOperation(findSpherePenetrationOp, &args);
|
recurseTreeWithOperation(findSpherePenetrationOp, &args);
|
||||||
if (penetratedObject) {
|
if (penetratedObject) {
|
||||||
|
@ -642,7 +647,7 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
|
||||||
if (node->hasContent()) {
|
if (node->hasContent()) {
|
||||||
glm::vec3 nodePenetration;
|
glm::vec3 nodePenetration;
|
||||||
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
|
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
|
||||||
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)TREE_SCALE);
|
args->penetration = addPenetrations(args->penetration, nodePenetration * static_cast<float>(TREE_SCALE));
|
||||||
args->found = true;
|
args->found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,7 +655,11 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
||||||
CapsuleArgs args = { start / (float)TREE_SCALE, end / (float)TREE_SCALE, radius / TREE_SCALE, penetration };
|
CapsuleArgs args = {
|
||||||
|
start / static_cast<float>(TREE_SCALE),
|
||||||
|
end / static_cast<float>(TREE_SCALE),
|
||||||
|
radius / static_cast<float>(TREE_SCALE),
|
||||||
|
penetration };
|
||||||
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
||||||
return args.found;
|
return args.found;
|
||||||
|
@ -719,8 +728,8 @@ int Octree::encodeTreeBitstream(OctreeElement* node,
|
||||||
// if childBytesWritten == 1 then something went wrong... that's not possible
|
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||||
assert(childBytesWritten != 1);
|
assert(childBytesWritten != 1);
|
||||||
|
|
||||||
// if includeColor and childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason
|
// if includeColor and childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some
|
||||||
// couldn't be written... so reset them here... This isn't true for the non-color included case
|
// reason couldn't be written... so reset them here... This isn't true for the non-color included case
|
||||||
if (params.includeColor && childBytesWritten == 2) {
|
if (params.includeColor && childBytesWritten == 2) {
|
||||||
childBytesWritten = 0;
|
childBytesWritten = 0;
|
||||||
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
|
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
|
||||||
|
@ -887,9 +896,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node,
|
||||||
bool keepDiggingDeeper = true; // Assuming we're in view we have a great work ethic, we're always ready for more!
|
bool keepDiggingDeeper = true; // Assuming we're in view we have a great work ethic, we're always ready for more!
|
||||||
|
|
||||||
// At any given point in writing the bitstream, the largest minimum we might need to flesh out the current level
|
// At any given point in writing the bitstream, the largest minimum we might need to flesh out the current level
|
||||||
// is 1 byte for child colors + 3*NUMBER_OF_CHILDREN bytes for the actual colors + 1 byte for child trees. There could be sub trees
|
// is 1 byte for child colors + 3*NUMBER_OF_CHILDREN bytes for the actual colors + 1 byte for child trees.
|
||||||
// below this point, which might take many more bytes, but that's ok, because we can always mark our subtrees as
|
// There could be sub trees below this point, which might take many more bytes, but that's ok, because we can
|
||||||
// not existing and stop the packet at this point, then start up with a new packet for the remaining sub trees.
|
// always mark our subtrees as not existing and stop the packet at this point, then start up with a new packet
|
||||||
|
// for the remaining sub trees.
|
||||||
unsigned char childrenExistInTreeBits = 0;
|
unsigned char childrenExistInTreeBits = 0;
|
||||||
unsigned char childrenExistInPacketBits = 0;
|
unsigned char childrenExistInPacketBits = 0;
|
||||||
unsigned char childrenColoredBits = 0;
|
unsigned char childrenColoredBits = 0;
|
||||||
|
@ -943,7 +953,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node,
|
||||||
if (params.stats && childNode) {
|
if (params.stats && childNode) {
|
||||||
params.stats->traversed(childNode);
|
params.stats->traversed(childNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for each child node in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
// for each child node in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||||
|
@ -1066,7 +1075,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node,
|
||||||
params.stats->skippedNoChange(childNode);
|
params.stats->skippedNoChange(childNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,15 +466,14 @@ void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssiz
|
||||||
|
|
||||||
|
|
||||||
void Particle::update() {
|
void Particle::update() {
|
||||||
|
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
int elapsed = now - _lastUpdated; // making this signed slightly improves clock skew behavior
|
float elapsed = static_cast<float>(now - _lastUpdated);
|
||||||
float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND);
|
_lastUpdated = now;
|
||||||
|
float timeElapsed = elapsed / static_cast<float>(USECS_PER_SECOND);
|
||||||
|
|
||||||
// calculate our default shouldDie state... then allow script to change it if it wants...
|
// calculate our default shouldDie state... then allow script to change it if it wants...
|
||||||
float velocityScalar = glm::length(getVelocity());
|
float velocityScalar = glm::length(getVelocity());
|
||||||
const float STILL_MOVING = 0.05 / TREE_SCALE;
|
const float STILL_MOVING = 0.05f / static_cast<float>(TREE_SCALE);
|
||||||
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
||||||
const float REALLY_OLD = 30.0f; // 30 seconds
|
const float REALLY_OLD = 30.0f; // 30 seconds
|
||||||
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
||||||
|
@ -510,8 +509,6 @@ void Particle::update() {
|
||||||
_velocity -= dampingResistance * timeElapsed;
|
_velocity -= dampingResistance * timeElapsed;
|
||||||
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastUpdated = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Particle::runUpdateScript() {
|
void Particle::runUpdateScript() {
|
||||||
|
|
|
@ -79,8 +79,8 @@ public:
|
||||||
uint64_t getLastEdited() const { return _lastEdited; }
|
uint64_t getLastEdited() const { return _lastEdited; }
|
||||||
|
|
||||||
/// lifetime of the particle in seconds
|
/// lifetime of the particle in seconds
|
||||||
float getLifetime() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
float getLifetime() const { return static_cast<float>(usecTimestampNow() - _created) / static_cast<float>(USECS_PER_SECOND); }
|
||||||
float getEditedAgo() const { return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; }
|
float getEditedAgo() const { return static_cast<float>(usecTimestampNow() - _lastEdited) / static_cast<float>(USECS_PER_SECOND); }
|
||||||
uint32_t getID() const { return _id; }
|
uint32_t getID() const { return _id; }
|
||||||
bool getShouldDie() const { return _shouldDie; }
|
bool getShouldDie() const { return _shouldDie; }
|
||||||
QString getScript() const { return _script; }
|
QString getScript() const { return _script; }
|
||||||
|
|
|
@ -67,10 +67,10 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
glm::vec3 center = particle->getPosition() * (float)TREE_SCALE;
|
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * (float)TREE_SCALE;
|
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
||||||
const float VOXEL_ELASTICITY = 1.4f;
|
const float VOXEL_ELASTICITY = 0.4f; // fraction of momentum conserved at collision
|
||||||
const float VOXEL_DAMPING = 0.0;
|
const float VOXEL_DAMPING = 0.0f;
|
||||||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
VoxelDetail* voxelDetails = NULL;
|
VoxelDetail* voxelDetails = NULL;
|
||||||
|
@ -88,10 +88,10 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) {
|
||||||
glm::vec3 center = particle->getPosition() * (float)TREE_SCALE;
|
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * (float)TREE_SCALE;
|
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
||||||
const float VOXEL_ELASTICITY = 1.4f;
|
const float VOXEL_ELASTICITY = 1.4f;
|
||||||
const float VOXEL_DAMPING = 0.0;
|
const float VOXEL_DAMPING = 0.0f;
|
||||||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
Particle* penetratedParticle;
|
Particle* penetratedParticle;
|
||||||
|
@ -132,10 +132,10 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("updateCollisionWithAvatars()...\n");
|
//printf("updateCollisionWithAvatars()...\n");
|
||||||
glm::vec3 center = particle->getPosition() * (float)TREE_SCALE;
|
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * (float)TREE_SCALE;
|
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
||||||
const float VOXEL_ELASTICITY = 1.4f;
|
const float VOXEL_ELASTICITY = 1.4f;
|
||||||
const float VOXEL_DAMPING = 0.0;
|
const float VOXEL_DAMPING = 0.0f;
|
||||||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
const PalmData* collidingPalm = NULL;
|
const PalmData* collidingPalm = NULL;
|
||||||
|
@ -144,23 +144,34 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
if (_selfAvatar) {
|
if (_selfAvatar) {
|
||||||
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
||||||
//printf("updateCollisionWithAvatars()..._selfAvatar=%p\n", avatar);
|
//printf("updateCollisionWithAvatars()..._selfAvatar=%p\n", avatar);
|
||||||
|
|
||||||
// check hands...
|
// check hands...
|
||||||
const HandData* handData = avatar->getHandData();
|
const HandData* handData = avatar->getHandData();
|
||||||
|
|
||||||
// if the particle penetrates the hand, then apply a hard collision
|
// TODO: combine hand and collision check into one. Note: would need to supply
|
||||||
|
// CollisionInfo class rather than just vec3 (penetration) so we can get back
|
||||||
|
// added velocity.
|
||||||
|
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
||||||
|
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
||||||
|
// apply a hard collision when ball collides with hand
|
||||||
penetration /= (float)TREE_SCALE;
|
penetration /= (float)TREE_SCALE;
|
||||||
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
||||||
if (collidingPalm) {
|
if (collidingPalm) {
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)TREE_SCALE;
|
glm::vec3 palmVelocity = collidingPalm->getVelocity() / static_cast<float>(TREE_SCALE);
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
||||||
addedVelocity = palmVelocity;
|
addedVelocity = palmVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
||||||
|
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
||||||
|
// apply hard collision when particle collides with avatar
|
||||||
|
penetration /= (float)TREE_SCALE;
|
||||||
|
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
||||||
|
glm::vec3 addedVelocity = avatar->getVelocity();
|
||||||
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,27 +181,33 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
|
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
|
||||||
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
|
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
|
||||||
AvatarData* avatar = (AvatarData*)node->getLinkedData();
|
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
||||||
|
AvatarData* avatar = static_cast<AvatarData*>(node->getLinkedData());
|
||||||
//printf("updateCollisionWithAvatars()...avatar=%p\n", avatar);
|
//printf("updateCollisionWithAvatars()...avatar=%p\n", avatar);
|
||||||
|
|
||||||
// check hands...
|
// check hands...
|
||||||
const HandData* handData = avatar->getHandData();
|
const HandData* handData = avatar->getHandData();
|
||||||
|
|
||||||
// if the particle penetrates the hand, then apply a hard collision
|
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
||||||
|
// apply a hard collision when ball collides with hand
|
||||||
penetration /= (float)TREE_SCALE;
|
penetration /= (float)TREE_SCALE;
|
||||||
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
||||||
if (collidingPalm) {
|
if (collidingPalm) {
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)TREE_SCALE;
|
glm::vec3 palmVelocity = collidingPalm->getVelocity() / static_cast<float>(TREE_SCALE);
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
||||||
addedVelocity = palmVelocity;
|
addedVelocity = palmVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
||||||
|
|
||||||
|
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
||||||
|
penetration /= (float)TREE_SCALE;
|
||||||
|
updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY);
|
||||||
|
glm::vec3 addedVelocity = avatar->getVelocity();
|
||||||
|
applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,21 +220,22 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
||||||
// Update the particle in response to a hard collision. Position will be reset exactly
|
// Update the particle in response to a hard collision. Position will be reset exactly
|
||||||
// to outside the colliding surface. Velocity will be modified according to elasticity.
|
// to outside the colliding surface. Velocity will be modified according to elasticity.
|
||||||
//
|
//
|
||||||
// if elasticity = 1.0, collision is inelastic.
|
// if elasticity = 0.0, collision is inelastic (vel normal to collision is lost)
|
||||||
// if elasticity > 1.0, collision is elastic.
|
// if elasticity = 1.0, collision is 100% elastic.
|
||||||
//
|
//
|
||||||
glm::vec3 position = particle->getPosition();
|
glm::vec3 position = particle->getPosition();
|
||||||
glm::vec3 velocity = particle->getVelocity();
|
glm::vec3 velocity = particle->getVelocity();
|
||||||
|
|
||||||
position -= penetration;
|
|
||||||
static float HALTING_VELOCITY = 0.2f / (float) TREE_SCALE;
|
|
||||||
// cancel out the velocity component in the direction of penetration
|
|
||||||
float penetrationLength = glm::length(penetration);
|
|
||||||
const float EPSILON = 0.0f;
|
const float EPSILON = 0.0f;
|
||||||
|
float velocityDotPenetration = glm::dot(velocity, penetration);
|
||||||
|
if (velocityDotPenetration > EPSILON) {
|
||||||
|
position -= penetration;
|
||||||
|
static float HALTING_VELOCITY = 0.2f / static_cast<float>(TREE_SCALE);
|
||||||
|
// cancel out the velocity component in the direction of penetration
|
||||||
|
|
||||||
if (penetrationLength > EPSILON) {
|
float penetrationLength = glm::length(penetration);
|
||||||
glm::vec3 direction = penetration / penetrationLength;
|
glm::vec3 direction = penetration / penetrationLength;
|
||||||
velocity -= glm::dot(velocity, direction) * direction * elasticity;
|
velocity -= (glm::dot(velocity, direction) * (1.0f + elasticity)) * direction;
|
||||||
velocity += addedVelocity;
|
velocity += addedVelocity;
|
||||||
velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f);
|
velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f);
|
||||||
if (glm::length(velocity) < HALTING_VELOCITY) {
|
if (glm::length(velocity) < HALTING_VELOCITY) {
|
||||||
|
@ -235,7 +253,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
||||||
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity,
|
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity,
|
||||||
particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getScript());
|
particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getScript());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency) {
|
void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency) {
|
||||||
|
|
||||||
|
@ -244,12 +262,12 @@ void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm
|
||||||
const float COLLISION_LOUDNESS = 1.f;
|
const float COLLISION_LOUDNESS = 1.f;
|
||||||
const float DURATION_SCALING = 0.004f;
|
const float DURATION_SCALING = 0.004f;
|
||||||
const float NOISE_SCALING = 0.1f;
|
const float NOISE_SCALING = 0.1f;
|
||||||
glm::vec3 velocity = particle->getVelocity() * (float)TREE_SCALE;
|
glm::vec3 velocity = particle->getVelocity() * static_cast<float>(TREE_SCALE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// how do we want to handle this??
|
// how do we want to handle this??
|
||||||
//
|
//
|
||||||
glm::vec3 gravity = particle->getGravity() * (float)TREE_SCALE;
|
glm::vec3 gravity = particle->getGravity() * static_cast<float>(TREE_SCALE);
|
||||||
|
|
||||||
if (glm::length(gravity) > EPSILON) {
|
if (glm::length(gravity) > EPSILON) {
|
||||||
// If gravity is on, remove the effect of gravity on velocity for this
|
// If gravity is on, remove the effect of gravity on velocity for this
|
||||||
|
@ -271,4 +289,4 @@ void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm
|
||||||
fmin(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f),
|
fmin(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f),
|
||||||
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, false);
|
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,9 +294,9 @@ void NodeList::clear() {
|
||||||
Node* node = nodeBucket[i % NODES_PER_BUCKET];
|
Node* node = nodeBucket[i % NODES_PER_BUCKET];
|
||||||
|
|
||||||
node->lock();
|
node->lock();
|
||||||
delete node;
|
notifyHooksOfKilledNode(&*node);
|
||||||
|
|
||||||
node = NULL;
|
delete node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_numNodes = 0;
|
_numNodes = 0;
|
||||||
|
|
Loading…
Reference in a new issue