mirror of
https://github.com/lubosz/overte.git
synced 2025-04-19 17:03:43 +02:00
Merge branch 'team-teaching' into text-renderer
This commit is contained in:
commit
76fc59675b
66 changed files with 839 additions and 494 deletions
|
@ -116,6 +116,7 @@
|
|||
#include "devices/TV3DManager.h"
|
||||
|
||||
#include "gpu/Batch.h"
|
||||
#include "gpu/Context.h"
|
||||
#include "gpu/GLBackend.h"
|
||||
|
||||
#include "scripting/AccountScriptingInterface.h"
|
||||
|
@ -688,6 +689,10 @@ Application::~Application() {
|
|||
// stop the glWidget frame timer so it doesn't call paintGL
|
||||
_glWidget->stopFrameTimer();
|
||||
|
||||
// remove avatars from physics engine
|
||||
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
|
||||
_physicsEngine.deleteObjects(DependencyManager::get<AvatarManager>()->getObjectsToDelete());
|
||||
|
||||
DependencyManager::destroy<OffscreenUi>();
|
||||
DependencyManager::destroy<AvatarManager>();
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
|
@ -831,6 +836,13 @@ void Application::initializeUi() {
|
|||
void Application::paintGL() {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
_glWidget->makeCurrent();
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
gpu::Context context;
|
||||
RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
|
||||
PerformanceTimer perfTimer("paintGL");
|
||||
//Need accurate frame timing for the oculus rift
|
||||
if (OculusManager::isConnected()) {
|
||||
|
@ -844,7 +856,7 @@ void Application::paintGL() {
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
_applicationOverlay.renderOverlay();
|
||||
_applicationOverlay.renderOverlay(&renderArgs);
|
||||
}
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
@ -893,22 +905,25 @@ void Application::paintGL() {
|
|||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
|
||||
if (getShadowsEnabled()) {
|
||||
updateShadowMap();
|
||||
renderArgs._renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
updateShadowMap(&renderArgs);
|
||||
}
|
||||
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
if (OculusManager::isConnected()) {
|
||||
//When in mirror mode, use camera rotation. Otherwise, use body rotation
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
OculusManager::display(_glWidget, _myCamera.getRotation(), _myCamera.getPosition(), _myCamera);
|
||||
OculusManager::display(_glWidget, &renderArgs, _myCamera.getRotation(), _myCamera.getPosition(), _myCamera);
|
||||
} else {
|
||||
OculusManager::display(_glWidget, _myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera);
|
||||
OculusManager::display(_glWidget, &renderArgs, _myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera);
|
||||
}
|
||||
} else if (TV3DManager::isConnected()) {
|
||||
|
||||
TV3DManager::display(_myCamera);
|
||||
TV3DManager::display(&renderArgs, _myCamera);
|
||||
|
||||
} else {
|
||||
DependencyManager::get<GlowEffect>()->prepare();
|
||||
DependencyManager::get<GlowEffect>()->prepare(&renderArgs);
|
||||
|
||||
// Viewport is assigned to the size of the framebuffer
|
||||
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||
|
@ -917,16 +932,16 @@ void Application::paintGL() {
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
displaySide(_myCamera);
|
||||
displaySide(&renderArgs, _myCamera);
|
||||
glPopMatrix();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||
_rearMirrorTools->render(true, _glWidget->mapFromGlobal(QCursor::pos()));
|
||||
_rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos()));
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||
renderRearViewMirror(_mirrorViewRect);
|
||||
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
||||
}
|
||||
|
||||
auto finalFbo = DependencyManager::get<GlowEffect>()->render();
|
||||
auto finalFbo = DependencyManager::get<GlowEffect>()->render(&renderArgs);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo));
|
||||
|
@ -2151,7 +2166,7 @@ void Application::init() {
|
|||
_physicsEngine.init();
|
||||
|
||||
EntityTree* tree = _entities.getTree();
|
||||
_entitySimulation.init(tree, &_physicsEngine, &_shapeManager, &_entityEditSender);
|
||||
_entitySimulation.init(tree, &_physicsEngine, &_entityEditSender);
|
||||
tree->setSimulation(&_entitySimulation);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
@ -2471,12 +2486,21 @@ void Application::update(float deltaTime) {
|
|||
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
|
||||
_entitySimulation.unlock();
|
||||
|
||||
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
|
||||
_physicsEngine.deleteObjects(avatarManager->getObjectsToDelete());
|
||||
_physicsEngine.addObjects(avatarManager->getObjectsToAdd());
|
||||
_physicsEngine.changeObjects(avatarManager->getObjectsToChange());
|
||||
|
||||
_physicsEngine.stepSimulation();
|
||||
|
||||
if (_physicsEngine.hasOutgoingChanges()) {
|
||||
_entitySimulation.lock();
|
||||
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
|
||||
_entitySimulation.unlock();
|
||||
|
||||
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
|
||||
avatarManager->handleCollisionEvents(_physicsEngine.getCollisionEvents());
|
||||
|
||||
_physicsEngine.dumpStatsIfNecessary();
|
||||
}
|
||||
}
|
||||
|
@ -2880,7 +2904,7 @@ glm::vec3 Application::getSunDirection() {
|
|||
// FIXME, preprocessor guard this check to occur only in DEBUG builds
|
||||
static QThread * activeRenderingThread = nullptr;
|
||||
|
||||
void Application::updateShadowMap() {
|
||||
void Application::updateShadowMap(RenderArgs* renderArgs) {
|
||||
activeRenderingThread = QThread::currentThread();
|
||||
|
||||
PerformanceTimer perfTimer("shadowMap");
|
||||
|
@ -3001,23 +3025,23 @@ void Application::updateShadowMap() {
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("avatarManager");
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(RenderArgs::SHADOW_RENDER_MODE);
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(renderArgs);
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("entities");
|
||||
_entities.render(RenderArgs::SHADOW_RENDER_MODE);
|
||||
_entities.render(renderArgs);
|
||||
}
|
||||
|
||||
// render JS/scriptable overlays
|
||||
{
|
||||
PerformanceTimer perfTimer("3dOverlays");
|
||||
_overlays.renderWorld(false, RenderArgs::SHADOW_RENDER_MODE);
|
||||
_overlays.renderWorld(renderArgs, false);
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("3dOverlaysFront");
|
||||
_overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE);
|
||||
_overlays.renderWorld(renderArgs, true);
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
@ -3085,15 +3109,16 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
QImage Application::renderAvatarBillboard() {
|
||||
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
|
||||
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||
|
||||
// the "glow" here causes an alpha of one
|
||||
Glower glower;
|
||||
Glower glower(renderArgs);
|
||||
|
||||
const int BILLBOARD_SIZE = 64;
|
||||
renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
||||
// TODO: Pass a RenderArgs to renderAvatarBillboard
|
||||
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
||||
BILLBOARD_SIZE, BILLBOARD_SIZE),
|
||||
true);
|
||||
|
||||
|
@ -3145,7 +3170,7 @@ const ViewFrustum* Application::getDisplayViewFrustum() const {
|
|||
return &_displayViewFrustum;
|
||||
}
|
||||
|
||||
void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) {
|
||||
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
|
||||
activeRenderingThread = QThread::currentThread();
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
|
@ -3184,7 +3209,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
if (theCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
if (renderSide != RenderArgs::MONO) {
|
||||
if (renderArgs->_renderSide != RenderArgs::MONO) {
|
||||
glm::mat4 invView = glm::inverse(_untranslatedViewMatrix);
|
||||
|
||||
viewTransform.evalFromRawMatrix(invView);
|
||||
|
@ -3315,7 +3340,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
// render JS/scriptable overlays
|
||||
{
|
||||
PerformanceTimer perfTimer("3dOverlays");
|
||||
_overlays.renderWorld(false);
|
||||
_overlays.renderWorld(renderArgs, false);
|
||||
}
|
||||
|
||||
// render models...
|
||||
|
@ -3337,7 +3362,9 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
if (theCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
}
|
||||
_entities.render(renderMode, renderSide, renderDebugFlags);
|
||||
renderArgs->_renderMode = renderMode;
|
||||
renderArgs->_debugFlags = renderDebugFlags;
|
||||
_entities.render(renderArgs);
|
||||
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) {
|
||||
// Restaure polygon mode
|
||||
|
@ -3358,8 +3385,9 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("avatars");
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE,
|
||||
false, selfAvatarOnly);
|
||||
renderArgs->_renderMode = mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE;
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(renderArgs, false, selfAvatarOnly);
|
||||
renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -3376,8 +3404,9 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("avatarsPostLighting");
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE,
|
||||
true, selfAvatarOnly);
|
||||
renderArgs->_renderMode = mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE;
|
||||
DependencyManager::get<AvatarManager>()->renderAvatars(renderArgs, true, selfAvatarOnly);
|
||||
renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
|
||||
}
|
||||
|
||||
//Render the sixense lasers
|
||||
|
@ -3401,7 +3430,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
"Application::displaySide() ... octree fades...");
|
||||
_octreeFadesLock.lockForWrite();
|
||||
for(std::vector<OctreeFade>::iterator fade = _octreeFades.begin(); fade != _octreeFades.end();) {
|
||||
fade->render();
|
||||
fade->render(renderArgs);
|
||||
if(fade->isDone()) {
|
||||
fade = _octreeFades.erase(fade);
|
||||
} else {
|
||||
|
@ -3426,8 +3455,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
{
|
||||
PerformanceTimer perfTimer("3dOverlaysFront");
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
Glower glower; // Sets alpha to 1.0
|
||||
_overlays.renderWorld(true);
|
||||
Glower glower(renderArgs); // Sets alpha to 1.0
|
||||
_overlays.renderWorld(renderArgs, true);
|
||||
}
|
||||
activeRenderingThread = nullptr;
|
||||
}
|
||||
|
@ -3505,7 +3534,7 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
|||
return screenPoint;
|
||||
}
|
||||
|
||||
void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||
void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) {
|
||||
// Grab current viewport to reset it at the end
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
|
@ -3565,11 +3594,11 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
|||
|
||||
// render rear mirror view
|
||||
glPushMatrix();
|
||||
displaySide(_mirrorCamera, true);
|
||||
displaySide(renderArgs, _mirrorCamera, true);
|
||||
glPopMatrix();
|
||||
|
||||
if (!billboard) {
|
||||
_rearMirrorTools->render(false, _glWidget->mapFromGlobal(QCursor::pos()));
|
||||
_rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
|
||||
// reset Viewport and projection matrix
|
||||
|
|
|
@ -268,9 +268,9 @@ public:
|
|||
virtual void setupWorldLight();
|
||||
virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera);
|
||||
|
||||
QImage renderAvatarBillboard();
|
||||
QImage renderAvatarBillboard(RenderArgs* renderArgs);
|
||||
|
||||
void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO);
|
||||
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false);
|
||||
|
||||
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
|
||||
/// the view matrix translation.
|
||||
|
@ -499,8 +499,8 @@ private:
|
|||
|
||||
glm::vec3 getSunDirection();
|
||||
|
||||
void updateShadowMap();
|
||||
void renderRearViewMirror(const QRect& region, bool billboard = false);
|
||||
void updateShadowMap(RenderArgs* renderArgs);
|
||||
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false);
|
||||
void setMenuShortcutsEnabled(bool enabled);
|
||||
|
||||
static void attachNewHeadToNode(Node *newNode);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "AvatarManager.h"
|
||||
#include "AvatarMotionState.h"
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "Menu.h"
|
||||
|
@ -268,7 +269,7 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
|||
return displayNameRenderer;
|
||||
}
|
||||
|
||||
void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) {
|
||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
@ -339,7 +340,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode rend
|
|||
// simple frustum check
|
||||
float boundingRadius = getBillboardSize();
|
||||
ViewFrustum* frustum = nullptr;
|
||||
if (renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
frustum = Application::getInstance()->getShadowViewFrustum();
|
||||
} else {
|
||||
frustum = Application::getInstance()->getDisplayViewFrustum();
|
||||
|
@ -365,14 +366,14 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode rend
|
|||
GLOW_FROM_AVERAGE_LOUDNESS = 0.0f;
|
||||
}
|
||||
|
||||
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == RenderArgs::NORMAL_RENDER_MODE
|
||||
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderArgs->_renderMode == RenderArgs::NORMAL_RENDER_MODE
|
||||
? 1.0f
|
||||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||
|
||||
// render body
|
||||
renderBody(frustum, renderMode, postLighting, glowLevel);
|
||||
renderBody(renderArgs, frustum, postLighting, glowLevel);
|
||||
|
||||
if (!postLighting && renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||
if (!postLighting && renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||
// add local lights
|
||||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||
const float LIGHT_EXPONENT = 1.0f;
|
||||
|
@ -396,10 +397,10 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode rend
|
|||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
if (renderHead && shouldRenderHead(cameraPosition, renderMode)) {
|
||||
if (renderHead && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderBounding && shouldRenderHead(cameraPosition, renderMode)) {
|
||||
if (renderBounding && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
_skeletonModel.renderBoundingCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
|
@ -436,7 +437,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode rend
|
|||
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
||||
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
||||
|
||||
if (renderMode == RenderArgs::NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
|
||||
if (renderArgs->_renderMode == RenderArgs::NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
|
||||
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
|
@ -455,8 +456,8 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode rend
|
|||
}
|
||||
|
||||
const float DISPLAYNAME_DISTANCE = 20.0f;
|
||||
setShowDisplayName(renderMode == RenderArgs::NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
||||
if (!postLighting || renderMode != RenderArgs::NORMAL_RENDER_MODE || (isMyAvatar() &&
|
||||
setShowDisplayName(renderArgs->_renderMode == RenderArgs::NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
||||
if (!postLighting || renderArgs->_renderMode != RenderArgs::NORMAL_RENDER_MODE || (isMyAvatar() &&
|
||||
Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) {
|
||||
return;
|
||||
}
|
||||
|
@ -479,13 +480,12 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
return glm::angleAxis(angle * proportion, axis);
|
||||
}
|
||||
|
||||
void Avatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||
Model::RenderMode modelRenderMode = renderMode;
|
||||
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
{
|
||||
Glower glower(glowLevel);
|
||||
Glower glower(renderArgs, glowLevel);
|
||||
|
||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
if (postLighting || renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
if (postLighting || renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard();
|
||||
}
|
||||
|
@ -493,18 +493,16 @@ void Avatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode rende
|
|||
}
|
||||
|
||||
if (postLighting) {
|
||||
getHand()->render(false, modelRenderMode);
|
||||
getHand()->render(renderArgs, false);
|
||||
} else {
|
||||
RenderArgs args;
|
||||
args._viewFrustum = renderFrustum;
|
||||
_skeletonModel.render(1.0f, modelRenderMode, &args);
|
||||
renderAttachments(renderMode, &args);
|
||||
_skeletonModel.render(renderArgs, 1.0f);
|
||||
renderAttachments(renderArgs);
|
||||
}
|
||||
}
|
||||
getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting);
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
|
||||
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const {
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -528,11 +526,11 @@ void Avatar::simulateAttachments(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) {
|
||||
void Avatar::renderAttachments(RenderArgs* args) {
|
||||
// RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
|
||||
// RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
|
||||
foreach (Model* model, _attachmentModels) {
|
||||
model->render(1.0f, renderMode, args);
|
||||
model->render(args, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -972,6 +970,9 @@ int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) {
|
|||
|
||||
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
|
||||
_moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD;
|
||||
if (_moving && _motionState) {
|
||||
_motionState->addDirtyFlags(EntityItem::DIRTY_POSITION);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -1087,20 +1088,15 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
|
|||
|
||||
}
|
||||
|
||||
// virtual
|
||||
void Avatar::rebuildSkeletonBody() {
|
||||
/* TODO: implement this and remove override from MyAvatar (when we have AvatarMotionStates working)
|
||||
if (_motionState) {
|
||||
// compute localAABox
|
||||
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
|
||||
float radius = capsule.getRadius();
|
||||
float height = 2.0f * (capsule.getHalfHeight() + radius);
|
||||
glm::vec3 corner(-radius, -0.5f * height, -radius);
|
||||
corner += _skeletonModel.getBoundingShapeOffset();
|
||||
glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
|
||||
//_characterController.setLocalBoundingBox(corner, scale);
|
||||
_motionState->setBoundingBox(corner, scale);
|
||||
}
|
||||
*/
|
||||
// virtual
|
||||
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
|
||||
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
|
||||
shapeInfo.setCapsuleY(capsule.getRadius(), capsule.getHalfHeight());
|
||||
shapeInfo.setOffset(_skeletonModel.getBoundingShapeOffset());
|
||||
}
|
||||
|
||||
// virtual
|
||||
void Avatar::rebuildSkeletonBody() {
|
||||
DependencyManager::get<AvatarManager>()->updateAvatarPhysicsShape(getSessionUUID());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
#include <QtCore/QUuid>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Recorder.h"
|
||||
#include "SkeletonModel.h"
|
||||
#include "world.h"
|
||||
|
||||
|
@ -55,6 +55,7 @@ enum ScreenTintLayer {
|
|||
NUM_SCREEN_TINT_LAYERS
|
||||
};
|
||||
|
||||
class AvatarMotionState;
|
||||
class Texture;
|
||||
|
||||
class Avatar : public AvatarData {
|
||||
|
@ -68,7 +69,7 @@ public:
|
|||
void init();
|
||||
void simulate(float deltaTime);
|
||||
|
||||
virtual void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE,
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition,
|
||||
bool postLighting = false);
|
||||
|
||||
//setters
|
||||
|
@ -146,9 +147,9 @@ public:
|
|||
|
||||
Q_INVOKABLE glm::vec3 getNeckPosition() const;
|
||||
|
||||
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
|
||||
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
|
||||
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
|
||||
Q_INVOKABLE const glm::vec3& getAcceleration() const { return _acceleration; }
|
||||
Q_INVOKABLE const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
|
||||
Q_INVOKABLE const glm::vec3& getAngularAcceleration() const { return _angularAcceleration; }
|
||||
|
||||
|
||||
/// Scales a world space position vector relative to the avatar position and scale
|
||||
|
@ -164,6 +165,10 @@ public:
|
|||
|
||||
virtual void rebuildSkeletonBody();
|
||||
|
||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
||||
|
||||
friend class AvatarManager;
|
||||
|
||||
signals:
|
||||
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
|
||||
|
||||
|
@ -208,11 +213,11 @@ protected:
|
|||
|
||||
float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD);
|
||||
void renderDisplayName();
|
||||
virtual void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const;
|
||||
|
||||
void simulateAttachments(float deltaTime);
|
||||
virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args);
|
||||
virtual void renderAttachments(RenderArgs* args);
|
||||
|
||||
virtual void updateJointMappings();
|
||||
|
||||
|
@ -231,7 +236,7 @@ private:
|
|||
|
||||
int _voiceSphereID;
|
||||
|
||||
//AvatarMotionState* _motionState = nullptr;
|
||||
AvatarMotionState* _motionState = nullptr;
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -92,22 +92,18 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
// simulate avatars
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
AvatarSharedPointer sharedAvatar = avatarIterator.value();
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data());
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
|
||||
|
||||
if (sharedAvatar == _myAvatar || !avatar->isInitialized()) {
|
||||
if (avatar == _myAvatar || !avatar->isInitialized()) {
|
||||
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
|
||||
// DO NOT update uninitialized Avatars
|
||||
// DO NOT update or fade out uninitialized Avatars
|
||||
++avatarIterator;
|
||||
continue;
|
||||
}
|
||||
if (!shouldKillAvatar(sharedAvatar)) {
|
||||
// this avatar's mixer is still around, go ahead and simulate it
|
||||
} else if (avatar->shouldDie()) {
|
||||
_avatarFades.push_back(avatarIterator.value());
|
||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||
} else {
|
||||
avatar->simulate(deltaTime);
|
||||
++avatarIterator;
|
||||
} else {
|
||||
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
|
||||
avatarIterator = erase(avatarIterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +111,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
simulateAvatarFades(deltaTime);
|
||||
}
|
||||
|
||||
void AvatarManager::renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) {
|
||||
void AvatarManager::renderAvatars(RenderArgs* renderArgs, bool postLighting, bool selfAvatarOnly) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::renderAvatars()");
|
||||
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderLookAtVectors);
|
||||
|
@ -129,14 +125,14 @@ void AvatarManager::renderAvatars(RenderArgs::RenderMode renderMode, bool postLi
|
|||
if (!avatar->isInitialized()) {
|
||||
continue;
|
||||
}
|
||||
avatar->render(cameraPosition, renderMode, postLighting);
|
||||
avatar->render(renderArgs, cameraPosition, postLighting);
|
||||
avatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
renderAvatarFades(cameraPosition, renderMode);
|
||||
renderAvatarFades(renderArgs, cameraPosition);
|
||||
}
|
||||
} else {
|
||||
// just render myAvatar
|
||||
_myAvatar->render(cameraPosition, renderMode, postLighting);
|
||||
_myAvatar->render(renderArgs, cameraPosition, postLighting);
|
||||
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
}
|
||||
|
@ -159,14 +155,14 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) {
|
||||
void AvatarManager::renderAvatarFades(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||
// render avatar fades
|
||||
Glower glower(renderMode == RenderArgs::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
||||
Glower glower(renderArgs, renderArgs->_renderMode == RenderArgs::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
||||
|
||||
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
||||
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
||||
if (avatar != static_cast<Avatar*>(_myAvatar.data()) && avatar->isInitialized()) {
|
||||
avatar->render(cameraPosition, renderMode);
|
||||
avatar->render(renderArgs, cameraPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,24 +171,52 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
|||
return AvatarSharedPointer(new Avatar());
|
||||
}
|
||||
|
||||
AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) {
|
||||
if (iterator.key() != MY_AVATAR_KEY) {
|
||||
if (reinterpret_cast<Avatar*>(iterator.value().data())->isInitialized()) {
|
||||
_avatarFades.push_back(iterator.value());
|
||||
// virtual
|
||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
||||
return avatar;
|
||||
}
|
||||
|
||||
// protected
|
||||
void AvatarManager::removeAvatarMotionState(Avatar* avatar) {
|
||||
AvatarMotionState* motionState= avatar->_motionState;
|
||||
if (motionState) {
|
||||
// clean up physics stuff
|
||||
motionState->clearObjectBackPointer();
|
||||
avatar->_motionState = nullptr;
|
||||
_avatarMotionStates.remove(motionState);
|
||||
_motionStatesToAdd.remove(motionState);
|
||||
_motionStatesToDelete.push_back(motionState);
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
|
||||
if (avatarIterator != _avatarHash.end()) {
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
|
||||
if (avatar != _myAvatar && avatar->isInitialized()) {
|
||||
removeAvatarMotionState(avatar);
|
||||
|
||||
_avatarFades.push_back(avatarIterator.value());
|
||||
_avatarHash.erase(avatarIterator);
|
||||
}
|
||||
return AvatarHashMap::erase(iterator);
|
||||
} else {
|
||||
// never remove _myAvatar from the list
|
||||
AvatarHash::iterator returnIterator = iterator;
|
||||
return ++returnIterator;
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::clearOtherAvatars() {
|
||||
// clear any avatars that came from an avatar-mixer
|
||||
AvatarHash::iterator removeAvatar = _avatarHash.begin();
|
||||
while (removeAvatar != _avatarHash.end()) {
|
||||
removeAvatar = erase(removeAvatar);
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
|
||||
if (avatar == _myAvatar || !avatar->isInitialized()) {
|
||||
// don't remove myAvatar or uninitialized avatars from the list
|
||||
++avatarIterator;
|
||||
} else {
|
||||
removeAvatarMotionState(avatar);
|
||||
_avatarFades.push_back(avatarIterator.value());
|
||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||
}
|
||||
}
|
||||
_myAvatar->clearLookAtTargetAvatar();
|
||||
}
|
||||
|
@ -215,3 +239,57 @@ QVector<AvatarManager::LocalLight> AvatarManager::getLocalLights() const {
|
|||
return _localLights;
|
||||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToDelete() {
|
||||
_tempMotionStates.clear();
|
||||
_tempMotionStates.swap(_motionStatesToDelete);
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToAdd() {
|
||||
_tempMotionStates.clear();
|
||||
|
||||
for (auto motionState : _motionStatesToAdd) {
|
||||
_tempMotionStates.push_back(motionState);
|
||||
}
|
||||
_motionStatesToAdd.clear();
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToChange() {
|
||||
_tempMotionStates.clear();
|
||||
for (auto state : _avatarMotionStates) {
|
||||
if (state->_dirtyFlags > 0) {
|
||||
_tempMotionStates.push_back(state);
|
||||
}
|
||||
}
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
void AvatarManager::handleOutgoingChanges(VectorOfMotionStates& motionStates) {
|
||||
// TODO: extract the MyAvatar results once we use a MotionState for it.
|
||||
}
|
||||
|
||||
void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) {
|
||||
// TODO: expose avatar collision events to JS
|
||||
}
|
||||
|
||||
void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) {
|
||||
AvatarHash::iterator avatarItr = _avatarHash.find(id);
|
||||
if (avatarItr != _avatarHash.end()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarItr.value().data());
|
||||
AvatarMotionState* motionState = avatar->_motionState;
|
||||
if (motionState) {
|
||||
motionState->addDirtyFlags(EntityItem::DIRTY_SHAPE);
|
||||
} else {
|
||||
ShapeInfo shapeInfo;
|
||||
avatar->computeShapeInfo(shapeInfo);
|
||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||
if (shape) {
|
||||
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
|
||||
avatar->_motionState = motionState;
|
||||
_motionStatesToAdd.insert(motionState);
|
||||
_avatarMotionStates.insert(motionState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
#include <QtCore/QSharedPointer>
|
||||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <PhysicsEngine.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "AvatarMotionState.h"
|
||||
|
||||
class MyAvatar;
|
||||
|
||||
|
@ -37,7 +39,7 @@ public:
|
|||
|
||||
void updateMyAvatar(float deltaTime);
|
||||
void updateOtherAvatars(float deltaTime);
|
||||
void renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false);
|
||||
void renderAvatars(RenderArgs* renderArgs, bool postLighting = false, bool selfAvatarOnly = false);
|
||||
|
||||
void clearOtherAvatars();
|
||||
|
||||
|
@ -51,6 +53,14 @@ public:
|
|||
|
||||
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
|
||||
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
|
||||
|
||||
VectorOfMotionStates& getObjectsToDelete();
|
||||
VectorOfMotionStates& getObjectsToAdd();
|
||||
VectorOfMotionStates& getObjectsToChange();
|
||||
void handleOutgoingChanges(VectorOfMotionStates& motionStates);
|
||||
void handleCollisionEvents(CollisionEvents& collisionEvents);
|
||||
|
||||
void updateAvatarPhysicsShape(const QUuid& id);
|
||||
|
||||
public slots:
|
||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||
|
@ -60,12 +70,13 @@ private:
|
|||
AvatarManager(const AvatarManager& other);
|
||||
|
||||
void simulateAvatarFades(float deltaTime);
|
||||
void renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode);
|
||||
|
||||
AvatarSharedPointer newSharedAvatar();
|
||||
void renderAvatarFades(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
||||
|
||||
// virtual overrides
|
||||
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
virtual AvatarSharedPointer newSharedAvatar();
|
||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void removeAvatarMotionState(Avatar* avatar);
|
||||
virtual void removeAvatar(const QUuid& sessionUUID);
|
||||
|
||||
QVector<AvatarSharedPointer> _avatarFades;
|
||||
QSharedPointer<MyAvatar> _myAvatar;
|
||||
|
@ -74,6 +85,11 @@ private:
|
|||
QVector<AvatarManager::LocalLight> _localLights;
|
||||
|
||||
bool _shouldShowReceiveStats = false;
|
||||
|
||||
SetOfAvatarMotionStates _avatarMotionStates;
|
||||
SetOfMotionStates _motionStatesToAdd;
|
||||
VectorOfMotionStates _motionStatesToDelete;
|
||||
VectorOfMotionStates _tempMotionStates;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
|
||||
|
|
160
interface/src/avatar/AvatarMotionState.cpp
Normal file
160
interface/src/avatar/AvatarMotionState.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
//
|
||||
// AvatarMotionState.cpp
|
||||
// interface/src/avatar/
|
||||
//
|
||||
// Created by Andrew Meadows 2015.05.14
|
||||
// Copyright 2015 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 <PhysicsHelpers.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "AvatarMotionState.h"
|
||||
#include "BulletUtil.h"
|
||||
|
||||
AvatarMotionState::AvatarMotionState(Avatar* avatar, btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) {
|
||||
assert(_avatar);
|
||||
if (_shape) {
|
||||
_mass = 100.0f; // HACK
|
||||
}
|
||||
}
|
||||
|
||||
AvatarMotionState::~AvatarMotionState() {
|
||||
_avatar = nullptr;
|
||||
}
|
||||
|
||||
// virtual
|
||||
uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() {
|
||||
uint32_t dirtyFlags = 0;
|
||||
if (_body && _avatar) {
|
||||
dirtyFlags = _dirtyFlags;
|
||||
_dirtyFlags = 0;
|
||||
}
|
||||
return dirtyFlags;
|
||||
}
|
||||
|
||||
MotionType AvatarMotionState::computeObjectMotionType() const {
|
||||
// TODO?: support non-DYNAMIC motion for avatars? (e.g. when sitting)
|
||||
return MOTION_TYPE_DYNAMIC;
|
||||
}
|
||||
|
||||
// virtual and protected
|
||||
btCollisionShape* AvatarMotionState::computeNewShape() {
|
||||
if (_avatar) {
|
||||
ShapeInfo shapeInfo;
|
||||
_avatar->computeShapeInfo(shapeInfo);
|
||||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool AvatarMotionState::isMoving() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const {
|
||||
if (!_avatar) {
|
||||
return;
|
||||
}
|
||||
worldTrans.setOrigin(glmToBullet(getObjectPosition()));
|
||||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
if (_body) {
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||
if (!_avatar) {
|
||||
return;
|
||||
}
|
||||
// HACK: The PhysicsEngine does not actually move OTHER avatars -- instead it slaves their local RigidBody to the transform
|
||||
// as specified by a remote simulation. However, to give the remote simulation time to respond to our own objects we tie
|
||||
// the other avatar's body to its true position with a simple spring. This is a HACK that will have to be improved later.
|
||||
const float SPRING_TIMESCALE = 0.5f;
|
||||
float tau = PHYSICS_ENGINE_FIXED_SUBSTEP / SPRING_TIMESCALE;
|
||||
btVector3 currentPosition = worldTrans.getOrigin();
|
||||
btVector3 targetPosition = glmToBullet(getObjectPosition());
|
||||
btTransform newTransform;
|
||||
newTransform.setOrigin((1.0f - tau) * currentPosition + tau * targetPosition);
|
||||
newTransform.setRotation(glmToBullet(getObjectRotation()));
|
||||
_body->setWorldTransform(newTransform);
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
}
|
||||
|
||||
// These pure virtual methods must be implemented for each MotionState type
|
||||
// and make it possible to implement more complicated methods in this base class.
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectRestitution() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectFriction() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectLinearDamping() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectAngularDamping() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
glm::vec3 AvatarMotionState::getObjectPosition() const {
|
||||
return _avatar->getPosition();
|
||||
}
|
||||
|
||||
// virtual
|
||||
glm::quat AvatarMotionState::getObjectRotation() const {
|
||||
return _avatar->getOrientation();
|
||||
}
|
||||
|
||||
// virtual
|
||||
const glm::vec3& AvatarMotionState::getObjectLinearVelocity() const {
|
||||
return _avatar->getVelocity();
|
||||
}
|
||||
|
||||
// virtual
|
||||
const glm::vec3& AvatarMotionState::getObjectAngularVelocity() const {
|
||||
return _avatar->getAngularVelocity();
|
||||
}
|
||||
|
||||
// virtual
|
||||
const glm::vec3& AvatarMotionState::getObjectGravity() const {
|
||||
return _avatar->getAcceleration();
|
||||
}
|
||||
|
||||
// virtual
|
||||
const QUuid& AvatarMotionState::getObjectID() const {
|
||||
return _avatar->getSessionUUID();
|
||||
}
|
||||
|
||||
// virtual
|
||||
QUuid AvatarMotionState::getSimulatorID() const {
|
||||
return _avatar->getSessionUUID();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::bump() {
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::clearObjectBackPointer() {
|
||||
ObjectMotionState::clearObjectBackPointer();
|
||||
_avatar = nullptr;
|
||||
}
|
||||
|
||||
|
75
interface/src/avatar/AvatarMotionState.h
Normal file
75
interface/src/avatar/AvatarMotionState.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// AvatarMotionState.h
|
||||
// interface/src/avatar/
|
||||
//
|
||||
// Created by Andrew Meadows 2015.05.14
|
||||
// Copyright 2015 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_AvatarMotionState_h
|
||||
#define hifi_AvatarMotionState_h
|
||||
|
||||
#include <QSet>
|
||||
|
||||
#include <ObjectMotionState.h>
|
||||
|
||||
class Avatar;
|
||||
|
||||
class AvatarMotionState : public ObjectMotionState {
|
||||
public:
|
||||
AvatarMotionState(Avatar* avatar, btCollisionShape* shape);
|
||||
~AvatarMotionState();
|
||||
|
||||
virtual MotionType getMotionType() const { return _motionType; }
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags();
|
||||
|
||||
virtual MotionType computeObjectMotionType() const;
|
||||
|
||||
virtual bool isMoving() const;
|
||||
|
||||
// this relays incoming position/rotation to the RigidBody
|
||||
virtual void getWorldTransform(btTransform& worldTrans) const;
|
||||
|
||||
// this relays outgoing position/rotation to the EntityItem
|
||||
virtual void setWorldTransform(const btTransform& worldTrans);
|
||||
|
||||
|
||||
// These pure virtual methods must be implemented for each MotionState type
|
||||
// and make it possible to implement more complicated methods in this base class.
|
||||
|
||||
virtual float getObjectRestitution() const;
|
||||
virtual float getObjectFriction() const;
|
||||
virtual float getObjectLinearDamping() const;
|
||||
virtual float getObjectAngularDamping() const;
|
||||
|
||||
virtual glm::vec3 getObjectPosition() const;
|
||||
virtual glm::quat getObjectRotation() const;
|
||||
virtual const glm::vec3& getObjectLinearVelocity() const;
|
||||
virtual const glm::vec3& getObjectAngularVelocity() const;
|
||||
virtual const glm::vec3& getObjectGravity() const;
|
||||
|
||||
virtual const QUuid& getObjectID() const;
|
||||
|
||||
virtual QUuid getSimulatorID() const;
|
||||
virtual void bump();
|
||||
|
||||
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
|
||||
|
||||
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
|
||||
|
||||
friend class AvatarManager;
|
||||
|
||||
protected:
|
||||
virtual btCollisionShape* computeNewShape();
|
||||
virtual void clearObjectBackPointer();
|
||||
Avatar* _avatar;
|
||||
uint32_t _dirtyFlags;
|
||||
};
|
||||
|
||||
typedef QSet<AvatarMotionState*> SetOfAvatarMotionStates;
|
||||
|
||||
#endif // hifi_AvatarMotionState_h
|
|
@ -102,8 +102,8 @@ void Hand::resolvePenetrations() {
|
|||
}
|
||||
}
|
||||
|
||||
void Hand::render(bool isMine, Model::RenderMode renderMode) {
|
||||
if (renderMode != RenderArgs::SHADOW_RENDER_MODE &&
|
||||
void Hand::render(RenderArgs* renderArgs, bool isMine) {
|
||||
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) {
|
||||
// draw a green sphere at hand joint location, which is actually near the wrist)
|
||||
for (size_t i = 0; i < getNumPalms(); i++) {
|
||||
|
@ -119,7 +119,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) {
|
|||
}
|
||||
}
|
||||
|
||||
if (renderMode != RenderArgs::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) {
|
||||
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) {
|
||||
renderHandTargets(isMine);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
};
|
||||
|
||||
void simulate(float deltaTime, bool isMine);
|
||||
void render(bool isMine, Model::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||
void render(RenderArgs* renderArgs, bool isMine);
|
||||
|
||||
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
|
||||
|
||||
|
|
|
@ -262,15 +262,13 @@ void Head::relaxLean(float deltaTime) {
|
|||
_deltaLeanForward *= relaxationFactor;
|
||||
}
|
||||
|
||||
void Head::render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mode, bool postLighting) {
|
||||
void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting) {
|
||||
if (postLighting) {
|
||||
if (_renderLookatVectors) {
|
||||
renderLookatVectors(_leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition());
|
||||
renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition());
|
||||
}
|
||||
} else {
|
||||
RenderArgs args;
|
||||
args._viewFrustum = renderFrustum;
|
||||
_faceModel.render(alpha, mode, &args);
|
||||
_faceModel.render(renderArgs, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,9 +351,9 @@ void Head::addLeanDeltas(float sideways, float forward) {
|
|||
_deltaLeanForward += forward;
|
||||
}
|
||||
|
||||
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||
void Head::renderLookatVectors(RenderArgs* renderArgs, glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
DependencyManager::get<GlowEffect>()->begin();
|
||||
DependencyManager::get<GlowEffect>()->begin(renderArgs);
|
||||
|
||||
glLineWidth(2.0);
|
||||
|
||||
|
@ -364,7 +362,7 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
|
|||
geometryCache->renderLine(leftEyePosition, lookatPosition, startColor, endColor, _leftEyeLookAtID);
|
||||
geometryCache->renderLine(rightEyePosition, lookatPosition, startColor, endColor, _rightEyeLookAtID);
|
||||
|
||||
DependencyManager::get<GlowEffect>()->end();
|
||||
DependencyManager::get<GlowEffect>()->end(renderArgs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||
void render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mode, bool postLighting);
|
||||
void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting);
|
||||
void setScale(float scale);
|
||||
void setPosition(glm::vec3 position) { _position = position; }
|
||||
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
|
||||
|
@ -153,7 +153,7 @@ private:
|
|||
int _rightEyeLookAtID;
|
||||
|
||||
// private methods
|
||||
void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||
void renderLookatVectors(RenderArgs* renderArgs, glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||
void calculateMouthShapes();
|
||||
|
||||
friend class FaceModel;
|
||||
|
|
|
@ -328,13 +328,13 @@ void MyAvatar::renderDebugBodyPoints() {
|
|||
}
|
||||
|
||||
// virtual
|
||||
void MyAvatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) {
|
||||
void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
||||
// don't render if we've been asked to disable local rendering
|
||||
if (!_shouldRender) {
|
||||
return; // exit early
|
||||
}
|
||||
|
||||
Avatar::render(cameraPosition, renderMode, postLighting);
|
||||
Avatar::render(renderArgs, cameraPosition, postLighting);
|
||||
|
||||
// don't display IK constraints in shadow mode
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ShowIKConstraints) && postLighting) {
|
||||
|
@ -1166,7 +1166,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
|||
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
|
||||
}
|
||||
|
||||
void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
}
|
||||
|
@ -1190,28 +1190,25 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren
|
|||
}*/
|
||||
|
||||
// Render the body's voxels and head
|
||||
RenderArgs::RenderMode modelRenderMode = renderMode;
|
||||
if (!postLighting) {
|
||||
RenderArgs args;
|
||||
args._viewFrustum = renderFrustum;
|
||||
_skeletonModel.render(1.0f, modelRenderMode, &args);
|
||||
renderAttachments(renderMode, &args);
|
||||
_skeletonModel.render(renderArgs, 1.0f);
|
||||
renderAttachments(renderArgs);
|
||||
}
|
||||
|
||||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(cameraPos, renderMode)) {
|
||||
getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting);
|
||||
if (shouldRenderHead(renderArgs, cameraPos)) {
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
if (postLighting) {
|
||||
getHand()->render(true, modelRenderMode);
|
||||
getHand()->render(renderArgs, true);
|
||||
}
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const {
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
const Head* head = getHead();
|
||||
return (renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
return (renderArgs->_renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
}
|
||||
|
||||
|
@ -1474,7 +1471,8 @@ void MyAvatar::maybeUpdateBillboard() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
QImage image = Application::getInstance()->renderAvatarBillboard();
|
||||
RenderArgs renderArgs;
|
||||
QImage image = Application::getInstance()->renderAvatarBillboard(&renderArgs);
|
||||
_billboard.clear();
|
||||
QBuffer buffer(&_billboard);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
|
@ -1551,9 +1549,9 @@ void MyAvatar::updateMotionBehavior() {
|
|||
_feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations);
|
||||
}
|
||||
|
||||
void MyAvatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) {
|
||||
if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
Avatar::renderAttachments(renderMode, args);
|
||||
void MyAvatar::renderAttachments(RenderArgs* args) {
|
||||
if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
Avatar::renderAttachments(args);
|
||||
return;
|
||||
}
|
||||
const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry();
|
||||
|
@ -1563,7 +1561,7 @@ void MyAvatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs*
|
|||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
const QString& jointName = _attachmentData.at(i).jointName;
|
||||
if (jointName != headJointName && jointName != "Head") {
|
||||
_attachmentModels.at(i)->render(1.0f, renderMode, args);
|
||||
_attachmentModels.at(i)->render(args, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ public:
|
|||
void simulate(float deltaTime);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
|
||||
void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE, bool postLighting = false);
|
||||
void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||
bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const;
|
||||
void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false);
|
||||
void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f);
|
||||
bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const override;
|
||||
void renderDebugBodyPoints();
|
||||
|
||||
// setters
|
||||
|
@ -198,7 +198,7 @@ signals:
|
|||
void transformChanged();
|
||||
|
||||
protected:
|
||||
virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args);
|
||||
virtual void renderAttachments(RenderArgs* args);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
_headClipDistance(DEFAULT_NEAR_CLIP)
|
||||
{
|
||||
assert(_owningAvatar);
|
||||
_enableShapes = true;
|
||||
}
|
||||
|
||||
SkeletonModel::~SkeletonModel() {
|
||||
|
|
|
@ -465,7 +465,7 @@ void OculusManager::configureCamera(Camera& camera) {
|
|||
}
|
||||
|
||||
//Displays everything for the oculus, frame timing must be active
|
||||
void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) {
|
||||
void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) {
|
||||
|
||||
#ifdef DEBUG
|
||||
// Ensure the frame counter always increments by exactly 1
|
||||
|
@ -532,7 +532,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
|
|||
|
||||
//Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||
DependencyManager::get<GlowEffect>()->prepare();
|
||||
DependencyManager::get<GlowEffect>()->prepare(renderArgs);
|
||||
} else {
|
||||
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFBO));
|
||||
|
@ -613,7 +613,8 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
|
|||
|
||||
glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h);
|
||||
|
||||
qApp->displaySide(*_camera, false, RenderArgs::MONO);
|
||||
renderArgs->_renderSide = RenderArgs::MONO;
|
||||
qApp->displaySide(renderArgs, *_camera, false);
|
||||
qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera);
|
||||
});
|
||||
_activeEye = ovrEye_Count;
|
||||
|
@ -625,7 +626,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||
//Full texture viewport for glow effect
|
||||
glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h);
|
||||
finalFbo = DependencyManager::get<GlowEffect>()->render();
|
||||
finalFbo = DependencyManager::get<GlowEffect>()->render(renderArgs);
|
||||
} else {
|
||||
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "RenderArgs.h"
|
||||
|
||||
class Camera;
|
||||
class PalmData;
|
||||
class Text3DOverlay;
|
||||
|
@ -61,7 +63,7 @@ public:
|
|||
static void endFrameTiming();
|
||||
static bool allowSwap();
|
||||
static void configureCamera(Camera& camera);
|
||||
static void display(QGLWidget * glCanvas, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera);
|
||||
static void display(QGLWidget * glCanvas, RenderArgs* renderArgs, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera);
|
||||
static void reset();
|
||||
|
||||
/// param \yaw[out] yaw in radians
|
||||
|
|
|
@ -80,7 +80,7 @@ void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int scre
|
|||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void TV3DManager::display(Camera& whichCamera) {
|
||||
void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) {
|
||||
double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane
|
||||
double farZ = DEFAULT_FAR_CLIP; // far clipping plane
|
||||
|
||||
|
@ -93,7 +93,7 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
int portalH = deviceSize.height();
|
||||
|
||||
|
||||
DependencyManager::get<GlowEffect>()->prepare();
|
||||
DependencyManager::get<GlowEffect>()->prepare(renderArgs);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Camera eyeCamera;
|
||||
|
@ -118,7 +118,8 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
qApp->displaySide(eyeCamera, false, RenderArgs::MONO);
|
||||
renderArgs->_renderSide = RenderArgs::MONO;
|
||||
qApp->displaySide(renderArgs, eyeCamera, false);
|
||||
qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov);
|
||||
_activeEye = NULL;
|
||||
}, [&]{
|
||||
|
@ -128,7 +129,7 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
glPopMatrix();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
auto finalFbo = DependencyManager::get<GlowEffect>()->render();
|
||||
auto finalFbo = DependencyManager::get<GlowEffect>()->render(renderArgs);
|
||||
auto fboSize = finalFbo->getSize();
|
||||
// Get the ACTUAL device size for the BLIT
|
||||
deviceSize = qApp->getDeviceSize();
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
static void connect();
|
||||
static bool isConnected();
|
||||
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
|
||||
static void display(Camera& whichCamera);
|
||||
static void display(RenderArgs* renderArgs, Camera& whichCamera);
|
||||
static void overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,
|
||||
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane);
|
||||
private:
|
||||
|
|
|
@ -37,8 +37,8 @@ OctreeFade::OctreeFade(FadeDirection direction, float red, float green, float bl
|
|||
opacity = (direction == FADE_OUT) ? FADE_OUT_START : FADE_IN_START;
|
||||
}
|
||||
|
||||
void OctreeFade::render() {
|
||||
DependencyManager::get<GlowEffect>()->begin();
|
||||
void OctreeFade::render(RenderArgs* renderArgs) {
|
||||
DependencyManager::get<GlowEffect>()->begin(renderArgs);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glPushMatrix();
|
||||
|
@ -53,7 +53,7 @@ void OctreeFade::render() {
|
|||
glEnable(GL_LIGHTING);
|
||||
|
||||
|
||||
DependencyManager::get<GlowEffect>()->end();
|
||||
DependencyManager::get<GlowEffect>()->end(renderArgs);
|
||||
|
||||
opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
OctreeFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED,
|
||||
float green = DEFAULT_GREEN, float blue = DEFAULT_BLUE);
|
||||
|
||||
void render();
|
||||
void render(RenderArgs* renderArgs);
|
||||
bool isDone() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ ApplicationOverlay::~ApplicationOverlay() {
|
|||
}
|
||||
|
||||
// Renders the overlays either to a texture or to the screen
|
||||
void ApplicationOverlay::renderOverlay() {
|
||||
void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
|
||||
|
@ -222,7 +222,7 @@ void ApplicationOverlay::renderOverlay() {
|
|||
// give external parties a change to hook in
|
||||
emit qApp->renderingOverlay();
|
||||
|
||||
overlays.renderHUD();
|
||||
overlays.renderHUD(renderArgs);
|
||||
|
||||
renderPointers();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
ApplicationOverlay();
|
||||
~ApplicationOverlay();
|
||||
|
||||
void renderOverlay();
|
||||
void renderOverlay(RenderArgs* renderArgs);
|
||||
void displayOverlayTexture();
|
||||
void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov);
|
||||
void displayOverlayTextureHmd(Camera& whichCamera);
|
||||
|
|
|
@ -46,7 +46,7 @@ RearMirrorTools::RearMirrorTools(QRect& bounds) :
|
|||
_headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
|
||||
}
|
||||
|
||||
void RearMirrorTools::render(bool fullScreen, const QPoint & mousePosition) {
|
||||
void RearMirrorTools::render(RenderArgs* renderArgs, bool fullScreen, const QPoint & mousePosition) {
|
||||
if (fullScreen) {
|
||||
_fullScreen = true;
|
||||
displayIcon(QRect(QPoint(), qApp->getDeviceSize()), _shrinkIconRect, _closeTexture);
|
||||
|
|
|
@ -24,7 +24,7 @@ class RearMirrorTools : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
RearMirrorTools(QRect& bounds);
|
||||
void render(bool fullScreen, const QPoint & mousePos);
|
||||
void render(RenderArgs* renderArgs, bool fullScreen, const QPoint & mousePos);
|
||||
bool mousePressEvent(int x, int y);
|
||||
|
||||
static Setting::Handle<int> rearViewZoomLevel;
|
||||
|
|
|
@ -47,7 +47,7 @@ void LocalModelsOverlay::render(RenderArgs* args) {
|
|||
Application* app = Application::getInstance();
|
||||
glm::vec3 oldTranslation = app->getViewMatrixTranslation();
|
||||
app->setViewMatrixTranslation(oldTranslation + _position);
|
||||
_entityTreeRenderer->render();
|
||||
_entityTreeRenderer->render(args);
|
||||
Application::getInstance()->setViewMatrixTranslation(oldTranslation);
|
||||
} glPopMatrix();
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ void ModelOverlay::render(RenderArgs* args) {
|
|||
if (glowLevel > 0.0f) {
|
||||
glower = new Glower(glowLevel);
|
||||
}
|
||||
_model.render(getAlpha(), RenderArgs::DEFAULT_RENDER_MODE, args);
|
||||
_model.render(args, getAlpha());
|
||||
if (glower) {
|
||||
delete glower;
|
||||
}
|
||||
|
|
|
@ -82,34 +82,27 @@ void Overlays::update(float deltatime) {
|
|||
|
||||
}
|
||||
|
||||
void Overlays::renderHUD() {
|
||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||
QReadLocker lock(&_lock);
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
RenderArgs args(NULL, Application::getInstance()->getViewFrustum(),
|
||||
lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlaysHUD) {
|
||||
if (thisOverlay->is3D()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
thisOverlay->render(&args);
|
||||
thisOverlay->render(renderArgs);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
} else{
|
||||
thisOverlay->render(&args);
|
||||
thisOverlay->render(renderArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Overlays::renderWorld(bool drawFront,
|
||||
RenderArgs::RenderMode renderMode,
|
||||
RenderArgs::RenderSide renderSide,
|
||||
RenderArgs::DebugFlags renderDebugFlags) {
|
||||
void Overlays::renderWorld(RenderArgs* renderArgs, bool drawFront) {
|
||||
QReadLocker lock(&_lock);
|
||||
if (_overlaysWorld.size() == 0) {
|
||||
return;
|
||||
|
@ -123,11 +116,6 @@ void Overlays::renderWorld(bool drawFront,
|
|||
float myAvatarScale = 1.0f;
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
RenderArgs args(NULL, Application::getInstance()->getDisplayViewFrustum(),
|
||||
lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide, renderDebugFlags);
|
||||
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlaysWorld) {
|
||||
Base3DOverlay* overlay3D = static_cast<Base3DOverlay*>(thisOverlay);
|
||||
|
@ -154,7 +142,7 @@ void Overlays::renderWorld(bool drawFront,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
thisOverlay->render(&args);
|
||||
thisOverlay->render(renderArgs);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,10 +53,8 @@ public:
|
|||
~Overlays();
|
||||
void init();
|
||||
void update(float deltatime);
|
||||
void renderWorld(bool drawFront, RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO,
|
||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE);
|
||||
void renderHUD();
|
||||
void renderWorld(RenderArgs* renderArgs, bool drawFront);
|
||||
void renderHUD(RenderArgs* renderArgs);
|
||||
|
||||
public slots:
|
||||
/// adds an overlay with the specific properties
|
||||
|
|
|
@ -69,6 +69,7 @@ const quint32 AVATAR_MOTION_DEFAULTS =
|
|||
const quint32 AVATAR_MOTION_SCRIPTABLE_BITS =
|
||||
AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
|
||||
|
||||
const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND;
|
||||
|
||||
// Bitset of state flags - we store the key state, hand state, faceshift, chat circling, and existance of
|
||||
// referential data in this bit set. The hand state is an octal, but is split into two sections to maintain
|
||||
|
@ -290,7 +291,6 @@ public:
|
|||
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||
|
||||
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||
|
||||
const AABox& getLocalAABox() const { return _localAABox; }
|
||||
|
@ -301,8 +301,10 @@ public:
|
|||
int getReceiveRate() const;
|
||||
|
||||
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
|
||||
Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; }
|
||||
glm::vec3 getTargetVelocity() const { return _targetVelocity; }
|
||||
Q_INVOKABLE const glm::vec3& getVelocity() const { return _velocity; }
|
||||
const glm::vec3& getTargetVelocity() const { return _targetVelocity; }
|
||||
|
||||
bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; }
|
||||
|
||||
public slots:
|
||||
void sendAvatarDataPacket();
|
||||
|
|
|
@ -20,19 +20,6 @@ AvatarHashMap::AvatarHashMap() {
|
|||
connect(DependencyManager::get<NodeList>().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
|
||||
}
|
||||
|
||||
|
||||
AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) {
|
||||
qCDebug(avatars) << "Removing Avatar with UUID" << iterator.key() << "from AvatarHashMap.";
|
||||
return _avatarHash.erase(iterator);
|
||||
}
|
||||
|
||||
const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND;
|
||||
|
||||
bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) {
|
||||
return (sharedAvatar->getOwningAvatarMixer() == NULL
|
||||
|| sharedAvatar->getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS);
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
switch (packetTypeForPacket(datagram)) {
|
||||
case PacketTypeBulkAvatarData:
|
||||
|
@ -52,10 +39,6 @@ void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const
|
|||
}
|
||||
}
|
||||
|
||||
bool AvatarHashMap::containsAvatarWithDisplayName(const QString& displayName) {
|
||||
return !avatarWithDisplayName(displayName).isNull();
|
||||
}
|
||||
|
||||
bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) {
|
||||
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
|
||||
glm::vec3 avatarPosition = sharedAvatar->getPosition();
|
||||
|
@ -67,45 +50,19 @@ bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range
|
|||
return false;
|
||||
}
|
||||
|
||||
AvatarWeakPointer AvatarHashMap::avatarWithDisplayName(const QString& displayName) {
|
||||
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
|
||||
if (sharedAvatar->getDisplayName() == displayName) {
|
||||
// this is a match
|
||||
// check if this avatar should still be around
|
||||
if (!shouldKillAvatar(sharedAvatar)) {
|
||||
// we have a match, return the AvatarData
|
||||
return sharedAvatar;
|
||||
} else {
|
||||
// we should remove this avatar, but we might not be on a thread that is allowed
|
||||
// so we just return NULL to the caller
|
||||
return AvatarWeakPointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AvatarWeakPointer();
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarHashMap::newSharedAvatar() {
|
||||
return AvatarSharedPointer(new AvatarData());
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarHashMap::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID);
|
||||
|
||||
if (!matchingAvatar) {
|
||||
// insert the new avatar into our hash
|
||||
matchingAvatar = newSharedAvatar();
|
||||
|
||||
qCDebug(avatars) << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
|
||||
|
||||
matchingAvatar->setSessionUUID(sessionUUID);
|
||||
matchingAvatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
|
||||
_avatarHash.insert(sessionUUID, matchingAvatar);
|
||||
}
|
||||
|
||||
return matchingAvatar;
|
||||
AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
qCDebug(avatars) << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
|
||||
|
||||
AvatarSharedPointer avatar = newSharedAvatar();
|
||||
avatar->setSessionUUID(sessionUUID);
|
||||
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
_avatarHash.insert(sessionUUID, avatar);
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
|
||||
|
@ -118,10 +75,13 @@ void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QW
|
|||
bytesRead += NUM_BYTES_RFC4122_UUID;
|
||||
|
||||
if (sessionUUID != _lastOwnerSessionUUID) {
|
||||
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
|
||||
if (!avatar) {
|
||||
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
||||
}
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
|
||||
bytesRead += avatar->parseDataAtOffset(datagram, bytesRead);
|
||||
} else {
|
||||
// create a dummy AvatarData class to throw this data on the ground
|
||||
AvatarData dummyData;
|
||||
|
@ -145,24 +105,24 @@ void AvatarHashMap::processAvatarIdentityPacket(const QByteArray &packet, const
|
|||
identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> attachmentData >> displayName;
|
||||
|
||||
// mesh URL for a UUID, find avatar in our list
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
|
||||
if (matchingAvatar->getFaceModelURL() != faceMeshURL) {
|
||||
matchingAvatar->setFaceModelURL(faceMeshURL);
|
||||
}
|
||||
|
||||
if (matchingAvatar->getSkeletonModelURL() != skeletonURL) {
|
||||
matchingAvatar->setSkeletonModelURL(skeletonURL);
|
||||
}
|
||||
|
||||
if (matchingAvatar->getAttachmentData() != attachmentData) {
|
||||
matchingAvatar->setAttachmentData(attachmentData);
|
||||
}
|
||||
|
||||
if (matchingAvatar->getDisplayName() != displayName) {
|
||||
matchingAvatar->setDisplayName(displayName);
|
||||
}
|
||||
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
|
||||
if (!avatar) {
|
||||
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
||||
}
|
||||
if (avatar->getFaceModelURL() != faceMeshURL) {
|
||||
avatar->setFaceModelURL(faceMeshURL);
|
||||
}
|
||||
|
||||
if (avatar->getSkeletonModelURL() != skeletonURL) {
|
||||
avatar->setSkeletonModelURL(skeletonURL);
|
||||
}
|
||||
|
||||
if (avatar->getAttachmentData() != attachmentData) {
|
||||
avatar->setAttachmentData(attachmentData);
|
||||
}
|
||||
|
||||
if (avatar->getDisplayName() != displayName) {
|
||||
avatar->setDisplayName(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,24 +131,25 @@ void AvatarHashMap::processAvatarBillboardPacket(const QByteArray& packet, const
|
|||
int headerSize = numBytesForPacketHeader(packet);
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
|
||||
if (matchingAvatar->getBillboard() != billboard) {
|
||||
matchingAvatar->setBillboard(billboard);
|
||||
}
|
||||
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
|
||||
if (!avatar) {
|
||||
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
||||
}
|
||||
|
||||
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
|
||||
if (avatar->getBillboard() != billboard) {
|
||||
avatar->setBillboard(billboard);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarHashMap::processKillAvatar(const QByteArray& datagram) {
|
||||
// read the node id
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
// remove the avatar with that UUID from our hash, if it exists
|
||||
AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID);
|
||||
if (matchedAvatar != _avatarHash.end()) {
|
||||
erase(matchedAvatar);
|
||||
}
|
||||
removeAvatar(sessionUUID);
|
||||
}
|
||||
|
||||
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
|
||||
_avatarHash.remove(sessionUUID);
|
||||
}
|
||||
|
||||
void AvatarHashMap::sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID) {
|
||||
|
|
|
@ -36,28 +36,26 @@ public:
|
|||
|
||||
public slots:
|
||||
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
bool containsAvatarWithDisplayName(const QString& displayName);
|
||||
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
||||
AvatarWeakPointer avatarWithDisplayName(const QString& displayname);
|
||||
|
||||
private slots:
|
||||
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
|
||||
|
||||
protected:
|
||||
AvatarHashMap();
|
||||
virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
|
||||
bool shouldKillAvatar(const AvatarSharedPointer& sharedAvatar);
|
||||
|
||||
virtual AvatarSharedPointer newSharedAvatar();
|
||||
AvatarSharedPointer matchingOrNewAvatar(const QUuid& nodeUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
virtual void removeAvatar(const QUuid& sessionUUID);
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
|
||||
private:
|
||||
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarIdentityPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processKillAvatar(const QByteArray& datagram);
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
QUuid _lastOwnerSessionUUID;
|
||||
};
|
||||
|
||||
|
|
|
@ -474,13 +474,11 @@ void EntityTreeRenderer::applyZonePropertiesToScene(const ZoneEntityItem* zone)
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
|
||||
RenderArgs::RenderSide renderSide,
|
||||
RenderArgs::DebugFlags renderDebugFlags) {
|
||||
void EntityTreeRenderer::render(RenderArgs* renderArgs) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
Model::startScene(renderSide);
|
||||
Model::startScene(renderArgs->_renderSide);
|
||||
|
||||
ViewFrustum* frustum = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
|
||||
ViewFrustum* frustum = (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
|
||||
_viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum();
|
||||
|
||||
// Setup batch transform matrices
|
||||
|
@ -492,44 +490,44 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
|
|||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
RenderArgs args(this, frustum, getSizeScale(), getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide, renderDebugFlags, &batch);
|
||||
renderArgs->_renderer = this;
|
||||
renderArgs->_batch = &batch;
|
||||
|
||||
_tree->lockForRead();
|
||||
|
||||
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
|
||||
_bestZone = NULL;
|
||||
_bestZoneVolume = std::numeric_limits<float>::max();
|
||||
_tree->recurseTreeWithOperation(renderOperation, &args);
|
||||
_tree->recurseTreeWithOperation(renderOperation, renderArgs);
|
||||
|
||||
applyZonePropertiesToScene(_bestZone);
|
||||
|
||||
// we must call endScene while we still have the tree locked so that no one deletes a model
|
||||
// on us while rendering the scene
|
||||
Model::endScene(renderMode, &args);
|
||||
Model::endScene(renderArgs);
|
||||
_tree->unlock();
|
||||
|
||||
glPushMatrix();
|
||||
gpu::GLBackend::renderBatch(batch, true);
|
||||
renderArgs->_context->enqueueBatch(batch);
|
||||
glPopMatrix();
|
||||
|
||||
// stats...
|
||||
_meshesConsidered = args._meshesConsidered;
|
||||
_meshesRendered = args._meshesRendered;
|
||||
_meshesOutOfView = args._meshesOutOfView;
|
||||
_meshesTooSmall = args._meshesTooSmall;
|
||||
_meshesConsidered = renderArgs->_meshesConsidered;
|
||||
_meshesRendered = renderArgs->_meshesRendered;
|
||||
_meshesOutOfView = renderArgs->_meshesOutOfView;
|
||||
_meshesTooSmall = renderArgs->_meshesTooSmall;
|
||||
|
||||
_elementsTouched = args._elementsTouched;
|
||||
_itemsRendered = args._itemsRendered;
|
||||
_itemsOutOfView = args._itemsOutOfView;
|
||||
_itemsTooSmall = args._itemsTooSmall;
|
||||
_elementsTouched = renderArgs->_elementsTouched;
|
||||
_itemsRendered = renderArgs->_itemsRendered;
|
||||
_itemsOutOfView = renderArgs->_itemsOutOfView;
|
||||
_itemsTooSmall = renderArgs->_itemsTooSmall;
|
||||
|
||||
_materialSwitches = args._materialSwitches;
|
||||
_trianglesRendered = args._trianglesRendered;
|
||||
_quadsRendered = args._quadsRendered;
|
||||
_materialSwitches = renderArgs->_materialSwitches;
|
||||
_trianglesRendered = renderArgs->_trianglesRendered;
|
||||
_quadsRendered = renderArgs->_quadsRendered;
|
||||
|
||||
_translucentMeshPartsRendered = args._translucentMeshPartsRendered;
|
||||
_opaqueMeshPartsRendered = args._opaqueMeshPartsRendered;
|
||||
_translucentMeshPartsRendered = renderArgs->_translucentMeshPartsRendered;
|
||||
_opaqueMeshPartsRendered = renderArgs->_opaqueMeshPartsRendered;
|
||||
}
|
||||
deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup
|
||||
}
|
||||
|
@ -713,7 +711,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
|
||||
Glower* glower = NULL;
|
||||
if (entityItem->getGlowLevel() > 0.0f) {
|
||||
glower = new Glower(entityItem->getGlowLevel());
|
||||
glower = new Glower(args, entityItem->getGlowLevel());
|
||||
}
|
||||
entityItem->render(args);
|
||||
args->_itemsRendered++;
|
||||
|
|
|
@ -58,9 +58,7 @@ public:
|
|||
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO,
|
||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE);
|
||||
virtual void render(RenderArgs* renderArgs) override;
|
||||
|
||||
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem);
|
||||
virtual const Model* getModelForEntityItem(const EntityItem* entityItem);
|
||||
|
|
|
@ -15,9 +15,22 @@
|
|||
|
||||
using namespace gpu;
|
||||
|
||||
Context::Context() {
|
||||
}
|
||||
|
||||
Context::Context(const Context& context) {
|
||||
}
|
||||
|
||||
Context::~Context() {
|
||||
}
|
||||
|
||||
bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
|
||||
if (shader.isProgram()) {
|
||||
return GLBackend::makeProgram(shader, bindings);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::enqueueBatch(Batch& batch) {
|
||||
GLBackend::renderBatch(batch, true);
|
||||
}
|
||||
|
|
|
@ -43,18 +43,18 @@ void Mesh::addAttribute(Slot slot, const BufferView& buffer) {
|
|||
}
|
||||
|
||||
void Mesh::evalVertexFormat() {
|
||||
VertexFormat vf;
|
||||
auto vf = new VertexFormat();
|
||||
int channelNum = 0;
|
||||
if (hasVertexData()) {
|
||||
vf.setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0);
|
||||
vf->setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0);
|
||||
channelNum++;
|
||||
}
|
||||
for (auto attrib : _attributeBuffers) {
|
||||
vf.setAttribute(attrib.first, channelNum, attrib.second._element, 0);
|
||||
vf->setAttribute(attrib.first, channelNum, attrib.second._element, 0);
|
||||
channelNum++;
|
||||
}
|
||||
|
||||
_vertexFormat = vf;
|
||||
_vertexFormat.reset(vf);
|
||||
}
|
||||
|
||||
void Mesh::setIndexBuffer(const BufferView& buffer) {
|
||||
|
@ -112,12 +112,12 @@ const gpu::BufferStream Mesh::makeBufferStream() const {
|
|||
|
||||
int channelNum = 0;
|
||||
if (hasVertexData()) {
|
||||
stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat.getChannelStride(channelNum));
|
||||
stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat->getChannelStride(channelNum));
|
||||
channelNum++;
|
||||
}
|
||||
for (auto attrib : _attributeBuffers) {
|
||||
BufferView& view = attrib.second;
|
||||
stream.addBuffer(view._buffer, view._offset, _vertexFormat.getChannelStride(channelNum));
|
||||
stream.addBuffer(view._buffer, view._offset, _vertexFormat->getChannelStride(channelNum));
|
||||
channelNum++;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,14 +47,14 @@ public:
|
|||
void setVertexBuffer(const BufferView& buffer);
|
||||
const BufferView& getVertexBuffer() const { return _vertexBuffer; }
|
||||
uint getNumVertices() const { return _vertexBuffer.getNumElements(); }
|
||||
bool hasVertexData() const { return !_vertexBuffer._buffer; }
|
||||
bool hasVertexData() const { return _vertexBuffer._buffer.get() != nullptr; }
|
||||
|
||||
// Attribute Buffers
|
||||
int getNumAttributes() const { return _attributeBuffers.size(); }
|
||||
void addAttribute(Slot slot, const BufferView& buffer);
|
||||
|
||||
// Stream format
|
||||
const VertexFormat& getVertexFormat() const { return _vertexFormat; }
|
||||
const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; }
|
||||
|
||||
// Index Buffer
|
||||
void setIndexBuffer(const BufferView& buffer);
|
||||
|
@ -114,7 +114,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
VertexFormat _vertexFormat;
|
||||
gpu::Stream::FormatPointer _vertexFormat;
|
||||
|
||||
BufferView _vertexBuffer;
|
||||
BufferViewMap _attributeBuffers;
|
||||
|
|
|
@ -27,7 +27,7 @@ void ReceivedPacketProcessor::queueReceivedPacket(const SharedNodePointer& sendi
|
|||
_nodePacketCounts[sendingNode->getUUID()]++;
|
||||
unlock();
|
||||
|
||||
// Make sure to wake our actual processing thread because we now have packets for it to process.
|
||||
// Make sure to wake our actual processing thread because we now have packets for it to process.
|
||||
_hasPackets.wakeAll();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,7 @@ public:
|
|||
virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ }
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO,
|
||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE) { /* swallow these */ }
|
||||
virtual void render(RenderArgs* renderArgs) override { /* swallow these */ }
|
||||
|
||||
void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; }
|
||||
|
||||
|
|
|
@ -164,32 +164,29 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void OctreeRenderer::render(RenderArgs::RenderMode renderMode,
|
||||
RenderArgs::RenderSide renderSide,
|
||||
RenderArgs::DebugFlags renderDebugFlags) {
|
||||
RenderArgs args(this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide, renderDebugFlags);
|
||||
void OctreeRenderer::render(RenderArgs* renderArgs) {
|
||||
if (_tree) {
|
||||
renderArgs->_renderer = this;
|
||||
_tree->lockForRead();
|
||||
_tree->recurseTreeWithOperation(renderOperation, &args);
|
||||
_tree->recurseTreeWithOperation(renderOperation, renderArgs);
|
||||
_tree->unlock();
|
||||
}
|
||||
_meshesConsidered = args._meshesConsidered;
|
||||
_meshesRendered = args._meshesRendered;
|
||||
_meshesOutOfView = args._meshesOutOfView;
|
||||
_meshesTooSmall = args._meshesTooSmall;
|
||||
_meshesConsidered = renderArgs->_meshesConsidered;
|
||||
_meshesRendered = renderArgs->_meshesRendered;
|
||||
_meshesOutOfView = renderArgs->_meshesOutOfView;
|
||||
_meshesTooSmall = renderArgs->_meshesTooSmall;
|
||||
|
||||
_elementsTouched = args._elementsTouched;
|
||||
_itemsRendered = args._itemsRendered;
|
||||
_itemsOutOfView = args._itemsOutOfView;
|
||||
_itemsTooSmall = args._itemsTooSmall;
|
||||
_elementsTouched = renderArgs->_elementsTouched;
|
||||
_itemsRendered = renderArgs->_itemsRendered;
|
||||
_itemsOutOfView = renderArgs->_itemsOutOfView;
|
||||
_itemsTooSmall = renderArgs->_itemsTooSmall;
|
||||
|
||||
_materialSwitches = args._materialSwitches;
|
||||
_trianglesRendered = args._trianglesRendered;
|
||||
_quadsRendered = args._quadsRendered;
|
||||
_materialSwitches = renderArgs->_materialSwitches;
|
||||
_trianglesRendered = renderArgs->_trianglesRendered;
|
||||
_quadsRendered = renderArgs->_quadsRendered;
|
||||
|
||||
_translucentMeshPartsRendered = args._translucentMeshPartsRendered;
|
||||
_opaqueMeshPartsRendered = args._opaqueMeshPartsRendered;
|
||||
_translucentMeshPartsRendered = renderArgs->_translucentMeshPartsRendered;
|
||||
_opaqueMeshPartsRendered = renderArgs->_opaqueMeshPartsRendered;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,7 @@ public:
|
|||
virtual void init();
|
||||
|
||||
/// render the content of the octree
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO,
|
||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE);
|
||||
virtual void render(RenderArgs* renderArgs);
|
||||
|
||||
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||
|
|
|
@ -311,9 +311,11 @@ void DynamicCharacterController::updateShapeIfNecessary() {
|
|||
// create new shape
|
||||
_shape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
|
||||
|
||||
// HACK: use some simple mass property defaults for now
|
||||
float mass = 100.0f;
|
||||
btVector3 inertia(30.0f, 8.0f, 30.0f);
|
||||
|
||||
// create new body
|
||||
float mass = 1.0f;
|
||||
btVector3 inertia(1.0f, 1.0f, 1.0f);
|
||||
_rigidBody = new btRigidBody(mass, nullptr, _shape, inertia);
|
||||
_rigidBody->setSleepingThresholds(0.0f, 0.0f);
|
||||
_rigidBody->setAngularFactor(0.0f);
|
||||
|
|
|
@ -39,8 +39,9 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity
|
|||
_loopsSinceOwnershipBid(0),
|
||||
_loopsWithoutOwner(0)
|
||||
{
|
||||
_type = MOTION_STATE_TYPE_ENTITY;
|
||||
assert(entity != nullptr);
|
||||
_type = MOTIONSTATE_TYPE_ENTITY;
|
||||
assert(_entity != nullptr);
|
||||
setMass(_entity->computeMass());
|
||||
}
|
||||
|
||||
EntityMotionState::~EntityMotionState() {
|
||||
|
@ -88,7 +89,6 @@ void EntityMotionState::handleEasyChanges(uint32_t flags) {
|
|||
if ((flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
|
||||
_body->activate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,10 +98,9 @@ void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
||||
void EntityMotionState::clearEntity() {
|
||||
void EntityMotionState::clearObjectBackPointer() {
|
||||
ObjectMotionState::clearObjectBackPointer();
|
||||
_entity = nullptr;
|
||||
// set the type to INVALID so that external logic that pivots on the type won't try to access _entity
|
||||
_type = MOTION_STATE_TYPE_INVALID;
|
||||
}
|
||||
|
||||
MotionType EntityMotionState::computeObjectMotionType() const {
|
||||
|
@ -178,10 +177,14 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
|
||||
// virtual and protected
|
||||
btCollisionShape* EntityMotionState::computeNewShape() {
|
||||
if (_entity) {
|
||||
ShapeInfo shapeInfo;
|
||||
_entity->computeShapeInfo(shapeInfo);
|
||||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// RELIABLE_SEND_HACK: until we have truly reliable resends of non-moving updates
|
||||
|
@ -444,7 +447,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
_lastStep = step;
|
||||
}
|
||||
|
||||
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const {
|
||||
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
|
||||
uint32_t dirtyFlags = 0;
|
||||
if (_body && _entity) {
|
||||
dirtyFlags = _entity->getDirtyFlags();
|
||||
|
|
|
@ -43,14 +43,12 @@ public:
|
|||
// this relays outgoing position/rotation to the EntityItem
|
||||
virtual void setWorldTransform(const btTransform& worldTrans);
|
||||
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
|
||||
|
||||
bool isCandidateForOwnership(const QUuid& sessionID) const;
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const;
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags();
|
||||
|
||||
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
|
||||
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
|
||||
|
@ -62,7 +60,7 @@ public:
|
|||
virtual float getObjectAngularDamping() const { return _entity->getAngularDamping(); }
|
||||
|
||||
virtual glm::vec3 getObjectPosition() const { return _entity->getPosition() - ObjectMotionState::getWorldOffset(); }
|
||||
virtual const glm::quat& getObjectRotation() const { return _entity->getRotation(); }
|
||||
virtual glm::quat getObjectRotation() const { return _entity->getRotation(); }
|
||||
virtual const glm::vec3& getObjectLinearVelocity() const { return _entity->getVelocity(); }
|
||||
virtual const glm::vec3& getObjectAngularVelocity() const { return _entity->getAngularVelocity(); }
|
||||
virtual const glm::vec3& getObjectGravity() const { return _entity->getGravity(); }
|
||||
|
@ -82,8 +80,8 @@ public:
|
|||
friend class PhysicalEntitySimulation;
|
||||
|
||||
protected:
|
||||
void clearEntity();
|
||||
|
||||
virtual btCollisionShape* computeNewShape();
|
||||
virtual void clearObjectBackPointer();
|
||||
virtual void setMotionType(MotionType motionType);
|
||||
|
||||
EntityItem* _entity;
|
||||
|
|
|
@ -140,20 +140,14 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) {
|
|||
}
|
||||
|
||||
if (flags & EntityItem::DIRTY_MASS) {
|
||||
float mass = getMass();
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||
_body->setMassProps(mass, inertia);
|
||||
_body->updateInertiaTensor();
|
||||
updateBodyMassProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
if (flags & EntityItem::DIRTY_SHAPE) {
|
||||
// make sure the new shape is valid
|
||||
ShapeInfo shapeInfo;
|
||||
computeObjectShapeInfo(shapeInfo);
|
||||
btCollisionShape* newShape = getShapeManager()->getShape(shapeInfo);
|
||||
btCollisionShape* newShape = computeNewShape();
|
||||
if (!newShape) {
|
||||
qCDebug(physics) << "Warning: failed to generate new shape!";
|
||||
// failed to generate new shape! --> keep old shape and remove shape-change flag
|
||||
|
@ -168,17 +162,22 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
}
|
||||
}
|
||||
getShapeManager()->releaseShape(_shape);
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
} else {
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
if (_shape != newShape) {
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
} else {
|
||||
// huh... the shape didn't actually change, so we clear the DIRTY_SHAPE flag
|
||||
flags &= ~EntityItem::DIRTY_SHAPE;
|
||||
}
|
||||
}
|
||||
engine->reinsertObject(this);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
// it is possible that there are no HARD flags at this point (if DIRTY_SHAPE was removed)
|
||||
// so we check again befoe we reinsert:
|
||||
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
|
||||
engine->reinsertObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateBodyMaterialProperties() {
|
||||
|
@ -193,3 +192,11 @@ void ObjectMotionState::updateBodyVelocities() {
|
|||
setBodyGravity(getObjectGravity());
|
||||
_body->setActivationState(ACTIVE_TAG);
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateBodyMassProperties() {
|
||||
float mass = getMass();
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||
_body->setMassProps(mass, inertia);
|
||||
_body->updateInertiaTensor();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include <btBulletDynamicsCommon.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QSet>
|
||||
#include <QVector>
|
||||
|
||||
#include <EntityItem.h>
|
||||
|
||||
#include "ContactInfo.h"
|
||||
|
@ -27,9 +30,9 @@ enum MotionType {
|
|||
};
|
||||
|
||||
enum MotionStateType {
|
||||
MOTION_STATE_TYPE_INVALID,
|
||||
MOTION_STATE_TYPE_ENTITY,
|
||||
MOTION_STATE_TYPE_AVATAR
|
||||
MOTIONSTATE_TYPE_INVALID,
|
||||
MOTIONSTATE_TYPE_ENTITY,
|
||||
MOTIONSTATE_TYPE_AVATAR
|
||||
};
|
||||
|
||||
// The update flags trigger two varieties of updates: "hard" which require the body to be pulled
|
||||
|
@ -71,8 +74,9 @@ public:
|
|||
virtual void handleEasyChanges(uint32_t flags);
|
||||
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
|
||||
|
||||
virtual void updateBodyMaterialProperties();
|
||||
virtual void updateBodyVelocities();
|
||||
void updateBodyMaterialProperties();
|
||||
void updateBodyVelocities();
|
||||
virtual void updateBodyMassProperties();
|
||||
|
||||
MotionStateType getType() const { return _type; }
|
||||
virtual MotionType getMotionType() const { return _motionType; }
|
||||
|
@ -87,11 +91,9 @@ public:
|
|||
glm::vec3 getBodyLinearVelocity() const;
|
||||
glm::vec3 getBodyAngularVelocity() const;
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const = 0;
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() = 0;
|
||||
|
||||
virtual MotionType computeObjectMotionType() const = 0;
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0;
|
||||
|
||||
|
||||
btCollisionShape* getShape() const { return _shape; }
|
||||
btRigidBody* getRigidBody() const { return _body; }
|
||||
|
@ -109,7 +111,7 @@ public:
|
|||
virtual float getObjectAngularDamping() const = 0;
|
||||
|
||||
virtual glm::vec3 getObjectPosition() const = 0;
|
||||
virtual const glm::quat& getObjectRotation() const = 0;
|
||||
virtual glm::quat getObjectRotation() const = 0;
|
||||
virtual const glm::vec3& getObjectLinearVelocity() const = 0;
|
||||
virtual const glm::vec3& getObjectAngularVelocity() const = 0;
|
||||
virtual const glm::vec3& getObjectGravity() const = 0;
|
||||
|
@ -124,10 +126,15 @@ public:
|
|||
friend class PhysicsEngine;
|
||||
|
||||
protected:
|
||||
virtual void setMotionType(MotionType motionType);
|
||||
virtual btCollisionShape* computeNewShape() = 0;
|
||||
void setMotionType(MotionType motionType);
|
||||
|
||||
// clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer.
|
||||
virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; }
|
||||
|
||||
void setRigidBody(btRigidBody* body);
|
||||
|
||||
MotionStateType _type = MOTION_STATE_TYPE_INVALID; // type of MotionState
|
||||
MotionStateType _type = MOTIONSTATE_TYPE_INVALID; // type of MotionState
|
||||
MotionType _motionType; // type of motion: KINEMATIC, DYNAMIC, or STATIC
|
||||
|
||||
btCollisionShape* _shape;
|
||||
|
@ -137,4 +144,7 @@ protected:
|
|||
uint32_t _lastKinematicStep;
|
||||
};
|
||||
|
||||
typedef QSet<ObjectMotionState*> SetOfMotionStates;
|
||||
typedef QVector<ObjectMotionState*> VectorOfMotionStates;
|
||||
|
||||
#endif // hifi_ObjectMotionState_h
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntityMotionState.h"
|
||||
#include "PhysicalEntitySimulation.h"
|
||||
#include "PhysicsHelpers.h"
|
||||
#include "PhysicsLogging.h"
|
||||
#include "ShapeInfoUtil.h"
|
||||
#include "ShapeManager.h"
|
||||
|
||||
PhysicalEntitySimulation::PhysicalEntitySimulation() {
|
||||
|
@ -25,7 +23,6 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() {
|
|||
void PhysicalEntitySimulation::init(
|
||||
EntityTree* tree,
|
||||
PhysicsEngine* physicsEngine,
|
||||
ShapeManager* shapeManager,
|
||||
EntityEditPacketSender* packetSender) {
|
||||
assert(tree);
|
||||
setEntityTree(tree);
|
||||
|
@ -33,9 +30,6 @@ void PhysicalEntitySimulation::init(
|
|||
assert(physicsEngine);
|
||||
_physicsEngine = physicsEngine;
|
||||
|
||||
assert(shapeManager);
|
||||
_shapeManager = shapeManager;
|
||||
|
||||
assert(packetSender);
|
||||
_entityPacketSender = packetSender;
|
||||
}
|
||||
|
@ -60,7 +54,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) {
|
|||
void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
_pendingRemoves.insert(motionState);
|
||||
_outgoingChanges.remove(motionState);
|
||||
|
@ -109,7 +103,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
|
|||
if (entity) {
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
}
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
}
|
||||
|
||||
// then delete the objects (aka MotionStates)
|
||||
|
@ -135,7 +129,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToDelete() {
|
|||
if (entity) {
|
||||
_pendingAdds.remove(entity);
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
}
|
||||
_tempVector.push_back(motionState);
|
||||
}
|
||||
|
@ -158,16 +152,14 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
|
|||
} else if (entity->isReadyToComputeShape()) {
|
||||
ShapeInfo shapeInfo;
|
||||
entity->computeShapeInfo(shapeInfo);
|
||||
btCollisionShape* shape = _shapeManager->getShape(shapeInfo);
|
||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||
if (shape) {
|
||||
EntityMotionState* motionState = new EntityMotionState(shape, entity);
|
||||
entity->setPhysicsInfo(static_cast<void*>(motionState));
|
||||
motionState->setMass(entity->computeMass());
|
||||
_physicalObjects.insert(motionState);
|
||||
_tempVector.push_back(motionState);
|
||||
entityItr = _pendingAdds.erase(entityItr);
|
||||
} else {
|
||||
// TODO: Seth to look into why this case is hit.
|
||||
//qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName();
|
||||
++entityItr;
|
||||
}
|
||||
|
@ -192,7 +184,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio
|
|||
// walk the motionStates looking for those that correspond to entities
|
||||
for (auto stateItr : motionStates) {
|
||||
ObjectMotionState* state = &(*stateItr);
|
||||
if (state && state->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (state && state->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||
EntityItem* entity = entityState->getEntity();
|
||||
if (entity) {
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
#include <EntitySimulation.h>
|
||||
|
||||
#include "PhysicsEngine.h"
|
||||
#include "PhysicsTypedefs.h"
|
||||
|
||||
class EntityMotionState;
|
||||
class ShapeManager;
|
||||
#include "EntityMotionState.h"
|
||||
|
||||
typedef QSet<EntityMotionState*> SetOfEntityMotionStates;
|
||||
|
||||
|
@ -33,7 +30,7 @@ public:
|
|||
PhysicalEntitySimulation();
|
||||
~PhysicalEntitySimulation();
|
||||
|
||||
void init(EntityTree* tree, PhysicsEngine* engine, ShapeManager* shapeManager, EntityEditPacketSender* packetSender);
|
||||
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
|
||||
|
||||
protected: // only called by EntitySimulation
|
||||
// overrides for EntitySimulation
|
||||
|
@ -63,7 +60,6 @@ private:
|
|||
SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine
|
||||
VectorOfMotionStates _tempVector; // temporary array reference, valid immediately after getObjectsToRemove() (and friends)
|
||||
|
||||
ShapeManager* _shapeManager = nullptr;
|
||||
PhysicsEngine* _physicsEngine = nullptr;
|
||||
EntityEditPacketSender* _entityPacketSender = nullptr;
|
||||
|
||||
|
|
|
@ -318,16 +318,16 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() {
|
|||
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
|
||||
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
|
||||
|
||||
if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (A && A->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
QUuid idA = A->getObjectID();
|
||||
QUuid idB;
|
||||
if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
idB = B->getObjectID();
|
||||
}
|
||||
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset;
|
||||
glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB);
|
||||
_collisionEvents.push_back(Collision(type, idA, idB, position, penetration));
|
||||
} else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
} else if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
QUuid idB = B->getObjectID();
|
||||
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset;
|
||||
// NOTE: we're flipping the order of A and B (so that the first objectID is never NULL)
|
||||
|
|
|
@ -22,13 +22,11 @@
|
|||
#include "BulletUtil.h"
|
||||
#include "ContactInfo.h"
|
||||
#include "DynamicCharacterController.h"
|
||||
#include "PhysicsTypedefs.h"
|
||||
#include "ObjectMotionState.h"
|
||||
#include "ThreadSafeDynamicsWorld.h"
|
||||
|
||||
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
||||
|
||||
class ObjectMotionState;
|
||||
|
||||
// simple class for keeping track of contacts
|
||||
class ContactKey {
|
||||
public:
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// PhysicsTypedefs.h
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Andrew Meadows 2015.04.29
|
||||
// Copyright 2015 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_PhysicsTypedefs_h
|
||||
#define hifi_PhysicsTypedefs_h
|
||||
|
||||
#include <QSet>
|
||||
#include <QVector>
|
||||
|
||||
class ObjectMotionState;
|
||||
|
||||
typedef QSet<ObjectMotionState*> SetOfMotionStates;
|
||||
typedef QVector<ObjectMotionState*> VectorOfMotionStates;
|
||||
|
||||
#endif //hifi_PhysicsTypedefs_h
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// ShapeInfoUtil.cpp
|
||||
// ShapeFactory.cpp
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Andrew Meadows 2014.12.01
|
||||
|
@ -9,14 +9,16 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include <SharedUtil.h> // for MILLIMETERS_PER_METER
|
||||
|
||||
#include "ShapeInfoUtil.h"
|
||||
#include "ShapeFactory.h"
|
||||
#include "BulletUtil.h"
|
||||
|
||||
|
||||
|
||||
btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& points) {
|
||||
btConvexHullShape* ShapeFactory::createConvexHull(const QVector<glm::vec3>& points) {
|
||||
assert(points.size() > 0);
|
||||
|
||||
btConvexHullShape* hull = new btConvexHullShape();
|
||||
|
@ -57,9 +59,10 @@ btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& poi
|
|||
return hull;
|
||||
}
|
||||
|
||||
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||
btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
|
||||
btCollisionShape* shape = NULL;
|
||||
switch(info.getType()) {
|
||||
int type = info.getType();
|
||||
switch(type) {
|
||||
case SHAPE_TYPE_BOX: {
|
||||
shape = new btBoxShape(glmToBullet(info.getHalfExtents()));
|
||||
}
|
||||
|
@ -95,5 +98,17 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (shape && type != SHAPE_TYPE_COMPOUND) {
|
||||
if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) {
|
||||
// this shape has an offset, which we support by wrapping the true shape
|
||||
// in a btCompoundShape with a local transform
|
||||
auto compound = new btCompoundShape();
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
trans.setOrigin(glmToBullet(info.getOffset()));
|
||||
compound->addChildShape(trans, shape);
|
||||
shape = compound;
|
||||
}
|
||||
}
|
||||
return shape;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// ShapeInfoUtil.h
|
||||
// ShapeFactory.h
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Andrew Meadows 2014.12.01
|
||||
|
@ -9,8 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ShapeInfoUtil_h
|
||||
#define hifi_ShapeInfoUtil_h
|
||||
#ifndef hifi_ShapeFactory_h
|
||||
#define hifi_ShapeFactory_h
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -20,11 +20,11 @@
|
|||
// translates between ShapeInfo and btShape
|
||||
|
||||
// TODO: rename this to ShapeFactory
|
||||
namespace ShapeInfoUtil {
|
||||
namespace ShapeFactory {
|
||||
|
||||
btConvexHullShape* createConvexHull(const QVector<glm::vec3>& points);
|
||||
|
||||
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
||||
};
|
||||
|
||||
#endif // hifi_ShapeInfoUtil_h
|
||||
#endif // hifi_ShapeFactory_h
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "ShapeInfoUtil.h"
|
||||
#include "ShapeFactory.h"
|
||||
#include "ShapeManager.h"
|
||||
|
||||
ShapeManager::ShapeManager() {
|
||||
|
@ -46,7 +46,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
|
|||
shapeRef->refCount++;
|
||||
return shapeRef->shape;
|
||||
}
|
||||
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
|
||||
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
if (shape) {
|
||||
ShapeReference newRef;
|
||||
newRef.refCount = 1;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include <LinearMath/btQuickprof.h>
|
||||
|
||||
#include "ObjectMotionState.h"
|
||||
#include "ThreadSafeDynamicsWorld.h"
|
||||
|
||||
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <BulletDynamics/Dynamics/btRigidBody.h>
|
||||
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
|
||||
|
||||
#include "PhysicsTypedefs.h"
|
||||
#include "ObjectMotionState.h"
|
||||
|
||||
ATTRIBUTE_ALIGNED16(class) ThreadSafeDynamicsWorld : public btDiscreteDynamicsWorld {
|
||||
public:
|
||||
|
|
|
@ -94,7 +94,7 @@ void GlowEffect::init(bool enabled) {
|
|||
_enabled = enabled;
|
||||
}
|
||||
|
||||
void GlowEffect::prepare() {
|
||||
void GlowEffect::prepare(RenderArgs* renderArgs) {
|
||||
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
|
@ -105,19 +105,19 @@ void GlowEffect::prepare() {
|
|||
_isOddFrame = !_isOddFrame;
|
||||
}
|
||||
|
||||
void GlowEffect::begin(float intensity) {
|
||||
void GlowEffect::begin(RenderArgs* renderArgs, float intensity) {
|
||||
// store the current intensity and add the new amount
|
||||
_intensityStack.push(_intensity);
|
||||
glBlendColor(0.0f, 0.0f, 0.0f, _intensity += intensity);
|
||||
_isEmpty &= (_intensity == 0.0f);
|
||||
}
|
||||
|
||||
void GlowEffect::end() {
|
||||
void GlowEffect::end(RenderArgs* renderArgs) {
|
||||
// restore the saved intensity
|
||||
glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop());
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer GlowEffect::render() {
|
||||
gpu::FramebufferPointer GlowEffect::render(RenderArgs* renderArgs) {
|
||||
PerformanceTimer perfTimer("glowEffect");
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
@ -212,10 +212,14 @@ void GlowEffect::toggleGlowEffect(bool enabled) {
|
|||
}
|
||||
|
||||
Glower::Glower(float amount) {
|
||||
DependencyManager::get<GlowEffect>()->begin(amount);
|
||||
RenderArgs renderArgs;
|
||||
DependencyManager::get<GlowEffect>()->begin(&renderArgs, amount);
|
||||
}
|
||||
Glower::Glower(RenderArgs* renderArgs, float amount) : _renderArgs(renderArgs) {
|
||||
DependencyManager::get<GlowEffect>()->begin(_renderArgs, amount);
|
||||
}
|
||||
|
||||
Glower::~Glower() {
|
||||
DependencyManager::get<GlowEffect>()->end();
|
||||
DependencyManager::get<GlowEffect>()->end(_renderArgs);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <gpu/GPUConfig.h>
|
||||
#include <gpu/Framebuffer.h>
|
||||
|
||||
#include "RenderArgs.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QGLWidget>
|
||||
#include <QStack>
|
||||
|
@ -37,14 +39,14 @@ public:
|
|||
void init(bool enabled);
|
||||
|
||||
/// Prepares the glow effect for rendering the current frame. To be called before rendering the scene.
|
||||
void prepare();
|
||||
void prepare(RenderArgs* renderArgs);
|
||||
|
||||
/// Starts using the glow effect.
|
||||
/// \param intensity the desired glow intensity, from zero to one
|
||||
void begin(float intensity = 1.0f);
|
||||
void begin(RenderArgs* renderArgs, float intensity = 1.0f);
|
||||
|
||||
/// Stops using the glow effect.
|
||||
void end();
|
||||
void end(RenderArgs* renderArgs);
|
||||
|
||||
/// Returns the current glow intensity.
|
||||
float getIntensity() const { return _intensity; }
|
||||
|
@ -52,7 +54,7 @@ public:
|
|||
/// Renders the glow effect. To be called after rendering the scene.
|
||||
/// \param toTexture whether to render to a texture, rather than to the frame buffer
|
||||
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
|
||||
gpu::FramebufferPointer render();
|
||||
gpu::FramebufferPointer render(RenderArgs* renderArgs);
|
||||
|
||||
public slots:
|
||||
void toggleGlowEffect(bool enabled);
|
||||
|
@ -85,7 +87,11 @@ class Glower {
|
|||
public:
|
||||
|
||||
Glower(float amount = 1.0f);
|
||||
Glower(RenderArgs* renderArgs, float amount = 1.0f);
|
||||
~Glower();
|
||||
|
||||
private:
|
||||
RenderArgs* _renderArgs;
|
||||
};
|
||||
|
||||
#endif // hifi_GlowEffect_h
|
||||
|
|
|
@ -765,27 +765,29 @@ void Model::renderSetup(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
|
||||
bool Model::render(RenderArgs* renderArgs, float alpha) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
|
||||
// render the attachments
|
||||
foreach (Model* attachment, _attachments) {
|
||||
attachment->render(alpha, mode, args);
|
||||
attachment->render(renderArgs, alpha);
|
||||
}
|
||||
if (_meshStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderSetup(args);
|
||||
return renderCore(alpha, mode, args);
|
||||
renderSetup(renderArgs);
|
||||
return renderCore(renderArgs, alpha);
|
||||
}
|
||||
|
||||
bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||
bool Model::renderCore(RenderArgs* args, float alpha) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
if (!_viewState) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mode = args->_renderMode;
|
||||
|
||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||
_renderBatch.clear();
|
||||
gpu::Batch& batch = _renderBatch;
|
||||
|
@ -1844,7 +1846,7 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
|
|||
batch.setViewTransform(_transforms[0]);
|
||||
}
|
||||
|
||||
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||
void Model::endScene(RenderArgs* args) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
|
||||
|
||||
|
@ -1853,6 +1855,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
|||
glPushMatrix();
|
||||
#endif
|
||||
|
||||
auto mode = args->_renderMode;
|
||||
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
|
||||
if (args) {
|
||||
renderSide = args->_renderSide;
|
||||
|
|
|
@ -98,12 +98,12 @@ public:
|
|||
void reset();
|
||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||
|
||||
bool render(float alpha = 1.0f, RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||
bool render(RenderArgs* renderArgs, float alpha = 1.0f);
|
||||
|
||||
// Scene rendering support
|
||||
static void startScene(RenderArgs::RenderSide renderSide);
|
||||
bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL);
|
||||
static void endScene(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||
static void endScene(RenderArgs* args);
|
||||
|
||||
/// Sets the URL of the model to render.
|
||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||
|
@ -371,7 +371,7 @@ private:
|
|||
|
||||
// helper functions used by render() or renderInScene()
|
||||
void renderSetup(RenderArgs* args);
|
||||
bool renderCore(float alpha, RenderArgs::RenderMode mode, RenderArgs* args);
|
||||
bool renderCore(RenderArgs* args, float alpha);
|
||||
int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args = NULL,
|
||||
bool forceRenderMeshes = false);
|
||||
|
|
|
@ -16,6 +16,7 @@ class ViewFrustum;
|
|||
class OctreeRenderer;
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
class Context;
|
||||
}
|
||||
|
||||
class RenderArgs {
|
||||
|
@ -30,7 +31,8 @@ public:
|
|||
RENDER_DEBUG_SIMULATION_OWNERSHIP = 2,
|
||||
};
|
||||
|
||||
RenderArgs(OctreeRenderer* renderer = nullptr,
|
||||
RenderArgs(gpu::Context* context = nullptr,
|
||||
OctreeRenderer* renderer = nullptr,
|
||||
ViewFrustum* viewFrustum = nullptr,
|
||||
float sizeScale = 1.0f,
|
||||
int boundaryLevelAdjust = 0,
|
||||
|
@ -55,6 +57,7 @@ public:
|
|||
|
||||
int translucentMeshPartsRendered = 0,
|
||||
int opaqueMeshPartsRendered = 0) :
|
||||
_context(context),
|
||||
_renderer(renderer),
|
||||
_viewFrustum(viewFrustum),
|
||||
_sizeScale(sizeScale),
|
||||
|
@ -82,6 +85,7 @@ public:
|
|||
_opaqueMeshPartsRendered(opaqueMeshPartsRendered) {
|
||||
}
|
||||
|
||||
gpu::Context* _context;
|
||||
OctreeRenderer* _renderer;
|
||||
ViewFrustum* _viewFrustum;
|
||||
float _sizeScale;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
void ShapeInfo::clear() {
|
||||
_type = SHAPE_TYPE_NONE;
|
||||
_halfExtents = glm::vec3(0.0f);
|
||||
_halfExtents = _offset = glm::vec3(0.0f);
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
_halfExtents = halfExtents;
|
||||
break;
|
||||
}
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||
|
@ -85,6 +86,11 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) {
|
|||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
void ShapeInfo::setOffset(const glm::vec3& offset) {
|
||||
_offset = offset;
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
uint32_t ShapeInfo::getNumSubShapes() const {
|
||||
if (_type == SHAPE_TYPE_NONE) {
|
||||
return 0;
|
||||
|
@ -175,6 +181,7 @@ bool ShapeInfo::contains(const glm::vec3& point) const {
|
|||
const DoubleHashKey& ShapeInfo::getHash() const {
|
||||
// NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance.
|
||||
if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) {
|
||||
bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET;
|
||||
// The key is not yet cached therefore we must compute it! To this end we bypass the const-ness
|
||||
// of this method by grabbing a non-const pointer to "this" and a non-const reference to _doubleHashKey.
|
||||
ShapeInfo* thisPtr = const_cast<ShapeInfo*>(this);
|
||||
|
@ -190,9 +197,14 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash =
|
||||
DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++);
|
||||
hash ^= floatHash;
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
if (useOffset) {
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
}
|
||||
}
|
||||
key.setHash(hash);
|
||||
|
||||
|
@ -201,8 +213,12 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash =
|
||||
DoubleHashKey::hashFunction2((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
|
||||
uint32_t floatHash = DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
|
||||
if (useOffset) {
|
||||
floatHash ^= DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f));
|
||||
}
|
||||
hash += ~(floatHash << 17);
|
||||
hash ^= (floatHash >> 11);
|
||||
hash += (floatHash << 4);
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "DoubleHashKey.h"
|
||||
|
||||
const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored
|
||||
|
||||
enum ShapeType {
|
||||
SHAPE_TYPE_NONE,
|
||||
SHAPE_TYPE_BOX,
|
||||
|
@ -46,10 +49,12 @@ public:
|
|||
void setEllipsoid(const glm::vec3& halfExtents);
|
||||
void setConvexHulls(const QVector<QVector<glm::vec3>>& points);
|
||||
void setCapsuleY(float radius, float halfHeight);
|
||||
void setOffset(const glm::vec3& offset);
|
||||
|
||||
int getType() const { return _type; }
|
||||
|
||||
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
||||
const glm::vec3& getOffset() const { return _offset; }
|
||||
|
||||
const QVector<QVector<glm::vec3>>& getPoints() const { return _points; }
|
||||
uint32_t getNumSubShapes() const;
|
||||
|
@ -68,6 +73,7 @@ public:
|
|||
protected:
|
||||
ShapeType _type = SHAPE_TYPE_NONE;
|
||||
glm::vec3 _halfExtents = glm::vec3(0.0f);
|
||||
glm::vec3 _offset = glm::vec3(0.0f);
|
||||
DoubleHashKey _doubleHashKey;
|
||||
QVector<QVector<glm::vec3>> _points; // points for convex collision hulls
|
||||
QUrl _url; // url for model of convex collision hulls
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
|
||||
inline bool isValidScale(glm::vec3 scale) {
|
||||
bool result = scale.x != 0.0f && scale.y != 0.0f && scale.z != 0.0f;
|
||||
assert(result);
|
||||
// assert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool isValidScale(float scale) {
|
||||
bool result = scale != 0.0f;
|
||||
assert(result);
|
||||
// assert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <DoubleHashKey.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <ShapeInfoUtil.h>
|
||||
#include <ShapeFactory.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "ShapeInfoTests.h"
|
||||
|
@ -142,7 +142,7 @@ void ShapeInfoTests::testBoxShape() {
|
|||
info.setBox(halfExtents);
|
||||
DoubleHashKey key = info.getHash();
|
||||
|
||||
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
|
||||
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
if (!shape) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: NULL Box shape" << std::endl;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ void ShapeInfoTests::testSphereShape() {
|
|||
info.setSphere(radius);
|
||||
DoubleHashKey key = info.getHash();
|
||||
|
||||
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
|
||||
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
|
||||
ShapeInfo otherInfo = info;
|
||||
DoubleHashKey otherKey = otherInfo.getHash();
|
||||
|
@ -192,7 +192,7 @@ void ShapeInfoTests::testCylinderShape() {
|
|||
info.setCylinder(radius, height);
|
||||
DoubleHashKey key = info.getHash();
|
||||
|
||||
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
|
||||
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
|
||||
ShapeInfo otherInfo = info;
|
||||
DoubleHashKey otherKey = otherInfo.getHash();
|
||||
|
@ -217,7 +217,7 @@ void ShapeInfoTests::testCapsuleShape() {
|
|||
info.setCapsule(radius, height);
|
||||
DoubleHashKey key = info.getHash();
|
||||
|
||||
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
|
||||
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
|
||||
ShapeInfo otherInfo = info;
|
||||
DoubleHashKey otherKey = otherInfo.getHash();
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <ShapeInfoUtil.h>
|
||||
#include <ShapeManager.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
|
|
Loading…
Reference in a new issue