mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:58:03 +02:00
change how render engine is told about model position changes
This commit is contained in:
parent
5c28c0bba0
commit
bc99ef778c
11 changed files with 213 additions and 195 deletions
|
@ -1086,75 +1086,77 @@ void Application::paintGL() {
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("CameraUpdates");
|
PerformanceTimer perfTimer("CameraUpdates");
|
||||||
|
|
||||||
auto myAvatar = getMyAvatar();
|
auto myAvatar = getMyAvatar();
|
||||||
|
myAvatar->withReadLock([&] {
|
||||||
myAvatar->startCapture();
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson,
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson,
|
||||||
cameraMenuChanged();
|
!(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||||
}
|
cameraMenuChanged();
|
||||||
|
|
||||||
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
|
||||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
|
||||||
|
|
||||||
// Always use the default eye position, not the actual head eye position.
|
|
||||||
// Using the latter will cause the camera to wobble with idle animations,
|
|
||||||
// or with changes from the face tracker
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
|
||||||
if (isHMDMode()) {
|
|
||||||
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
|
||||||
_myCamera.setPosition(extractTranslation(camMat));
|
|
||||||
_myCamera.setRotation(glm::quat_cast(camMat));
|
|
||||||
} else {
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
|
||||||
_myCamera.setRotation(myAvatar->getHead()->getCameraOrientation());
|
|
||||||
}
|
}
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
|
||||||
if (isHMDMode()) {
|
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
||||||
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
_myCamera.setRotation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
|
||||||
auto worldBoomOffset = myAvatar->getOrientation() * (myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f));
|
// Always use the default eye position, not the actual head eye position.
|
||||||
_myCamera.setPosition(extractTranslation(hmdWorldMat) + worldBoomOffset);
|
// Using the latter will cause the camera to wobble with idle animations,
|
||||||
} else {
|
// or with changes from the face tracker
|
||||||
_myCamera.setRotation(myAvatar->getHead()->getOrientation());
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
if (isHMDMode()) {
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
+ _myCamera.getRotation()
|
_myCamera.setPosition(extractTranslation(camMat));
|
||||||
* (myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f)));
|
_myCamera.setRotation(glm::quat_cast(camMat));
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
||||||
+ myAvatar->getOrientation()
|
_myCamera.setRotation(myAvatar->getHead()->getCameraOrientation());
|
||||||
* (myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f)));
|
|
||||||
}
|
}
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
|
_myCamera.setRotation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
||||||
|
auto worldBoomOffset = myAvatar->getOrientation() *
|
||||||
|
(myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
_myCamera.setPosition(extractTranslation(hmdWorldMat) + worldBoomOffset);
|
||||||
|
} else {
|
||||||
|
_myCamera.setRotation(myAvatar->getHead()->getOrientation());
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ _myCamera.getRotation() *
|
||||||
|
(myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f)));
|
||||||
|
} else {
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ myAvatar->getOrientation() *
|
||||||
|
(myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
||||||
|
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)) * hmdRotation);
|
||||||
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
||||||
|
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
||||||
|
+ (myAvatar->getOrientation() *
|
||||||
|
glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))) * hmdOffset);
|
||||||
|
} else {
|
||||||
|
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
||||||
|
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
||||||
|
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
|
}
|
||||||
|
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||||
}
|
}
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
// Update camera position
|
||||||
if (isHMDMode()) {
|
if (!isHMDMode()) {
|
||||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
_myCamera.update(1.0f / _fps);
|
||||||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
|
||||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)) * hmdRotation);
|
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
|
||||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
|
||||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
|
||||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))) * hmdOffset);
|
|
||||||
} else {
|
|
||||||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
|
||||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
|
||||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
|
||||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
|
||||||
}
|
}
|
||||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
});
|
||||||
}
|
|
||||||
// Update camera position
|
|
||||||
if (!isHMDMode()) {
|
|
||||||
_myCamera.update(1.0f / _fps);
|
|
||||||
}
|
|
||||||
myAvatar->endCapture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary rendering pass
|
// Primary rendering pass
|
||||||
|
@ -3386,9 +3388,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
||||||
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
|
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||||
// Then we can move this logic into the Avatar::simulate call.
|
// Then we can move this logic into the Avatar::simulate call.
|
||||||
auto myAvatar = getMyAvatar();
|
auto myAvatar = getMyAvatar();
|
||||||
myAvatar->startRender();
|
myAvatar->withReadLock([&] {
|
||||||
myAvatar->preRender(renderArgs);
|
myAvatar->preRender(renderArgs);
|
||||||
myAvatar->endRender();
|
});
|
||||||
|
|
||||||
|
|
||||||
activeRenderingThread = QThread::currentThread();
|
activeRenderingThread = QThread::currentThread();
|
||||||
|
@ -3502,9 +3504,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
||||||
_renderEngine->setRenderContext(renderContext);
|
_renderEngine->setRenderContext(renderContext);
|
||||||
|
|
||||||
// Before the deferred pass, let's try to use the render engine
|
// Before the deferred pass, let's try to use the render engine
|
||||||
myAvatar->startRenderRun();
|
myAvatar->withReadLock([&] {
|
||||||
_renderEngine->run();
|
_renderEngine->run();
|
||||||
myAvatar->endRenderRun();
|
});
|
||||||
|
|
||||||
auto engineRC = _renderEngine->getRenderContext();
|
auto engineRC = _renderEngine->getRenderContext();
|
||||||
sceneInterface->setEngineFeedOpaqueItems(engineRC->_numFeedOpaqueItems);
|
sceneInterface->setEngineFeedOpaqueItems(engineRC->_numFeedOpaqueItems);
|
||||||
|
|
|
@ -303,8 +303,6 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
startRender();
|
|
||||||
|
|
||||||
auto& batch = *renderArgs->_batch;
|
auto& batch = *renderArgs->_batch;
|
||||||
|
|
||||||
if (glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), getPosition()) < 10.0f) {
|
if (glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), getPosition()) < 10.0f) {
|
||||||
|
@ -375,7 +373,6 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||||
endRender();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +526,6 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
renderDisplayName(batch, frustum, textPosition);
|
renderDisplayName(batch, frustum, textPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endRender();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
|
@ -993,23 +989,25 @@ void Avatar::setBillboard(const QByteArray& billboard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
startUpdate();
|
int bytesRead;
|
||||||
if (!_initialized) {
|
|
||||||
// now that we have data for this Avatar we are go for init
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// change in position implies movement
|
withWriteLock([&] {
|
||||||
glm::vec3 oldPosition = getPosition();
|
if (!_initialized) {
|
||||||
|
// now that we have data for this Avatar we are go for init
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
int bytesRead = AvatarData::parseDataFromBuffer(buffer);
|
// change in position implies movement
|
||||||
|
glm::vec3 oldPosition = getPosition();
|
||||||
|
|
||||||
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
|
bytesRead = AvatarData::parseDataFromBuffer(buffer);
|
||||||
_moving = glm::distance(oldPosition, getPosition()) > MOVE_DISTANCE_THRESHOLD;
|
|
||||||
if (_moving && _motionState) {
|
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
|
||||||
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
_moving = glm::distance(oldPosition, getPosition()) > MOVE_DISTANCE_THRESHOLD;
|
||||||
}
|
if (_moving && _motionState) {
|
||||||
endUpdate();
|
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
@ -1201,3 +1199,13 @@ glm::quat Avatar::getRightPalmRotation() {
|
||||||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
|
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
|
||||||
return rightRotation;
|
return rightRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::setPosition(const glm::vec3& position) {
|
||||||
|
AvatarData::setPosition(position);
|
||||||
|
updateAttitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::setOrientation(const glm::quat& orientation) {
|
||||||
|
AvatarData::setOrientation(orientation);
|
||||||
|
updateAttitude();
|
||||||
|
}
|
||||||
|
|
|
@ -174,6 +174,9 @@ public:
|
||||||
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
|
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
|
||||||
AvatarMotionState* getMotionState() { return _motionState; }
|
AvatarMotionState* getMotionState() { return _motionState; }
|
||||||
|
|
||||||
|
virtual void setPosition(const glm::vec3& position);
|
||||||
|
virtual void setOrientation(const glm::quat& orientation);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
glm::vec3 getLeftPalmPosition();
|
glm::vec3 getLeftPalmPosition();
|
||||||
glm::vec3 getLeftPalmVelocity();
|
glm::vec3 getLeftPalmVelocity();
|
||||||
|
|
|
@ -129,9 +129,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
} else {
|
} else {
|
||||||
avatar->startUpdate();
|
avatar->withWriteLock([&] {
|
||||||
avatar->simulate(deltaTime);
|
avatar->simulate(deltaTime);
|
||||||
avatar->endUpdate();
|
});
|
||||||
++avatarIterator;
|
++avatarIterator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,16 +150,16 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
while (fadingIterator != _avatarFades.end()) {
|
while (fadingIterator != _avatarFades.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||||
avatar->startUpdate();
|
avatar->withWriteLock([&] {
|
||||||
avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE, true);
|
avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE, true);
|
||||||
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
|
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
|
||||||
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
||||||
fadingIterator = _avatarFades.erase(fadingIterator);
|
fadingIterator = _avatarFades.erase(fadingIterator);
|
||||||
} else {
|
} else {
|
||||||
avatar->simulate(deltaTime);
|
avatar->simulate(deltaTime);
|
||||||
++fadingIterator;
|
++fadingIterator;
|
||||||
}
|
}
|
||||||
avatar->endUpdate();
|
});
|
||||||
}
|
}
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,11 @@ bool AvatarUpdate::process() {
|
||||||
//gets current lookat data, removes missing avatars, etc.
|
//gets current lookat data, removes missing avatars, etc.
|
||||||
manager->updateOtherAvatars(deltaSeconds);
|
manager->updateOtherAvatars(deltaSeconds);
|
||||||
|
|
||||||
myAvatar->startUpdate();
|
myAvatar->withWriteLock([&] {
|
||||||
qApp->updateMyAvatarLookAtPosition();
|
qApp->updateMyAvatarLookAtPosition();
|
||||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||||
manager->updateMyAvatar(deltaSeconds);
|
manager->updateMyAvatar(deltaSeconds);
|
||||||
myAvatar->endUpdate();
|
});
|
||||||
|
|
||||||
if (!isThreaded()) {
|
if (!isThreaded()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -110,51 +110,25 @@ void AvatarData::setBodyRoll(float bodyRoll) {
|
||||||
setOrientation(glm::quat(glm::radians(eulerAngles)));
|
setOrientation(glm::quat(glm::radians(eulerAngles)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarData::setPosition(const glm::vec3& position) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
SpatiallyNestable::setPosition(position);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarData::setOrientation(const glm::quat& orientation) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
SpatiallyNestable::setOrientation(orientation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// There are a number of possible strategies for this set of tools through endRender, below.
|
// There are a number of possible strategies for this set of tools through endRender, below.
|
||||||
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
||||||
avatarLock.lock();
|
withWriteLock([&] {
|
||||||
setPosition(position);
|
SpatiallyNestable::setPosition(position);
|
||||||
setOrientation(orientation);
|
SpatiallyNestable::setOrientation(orientation);
|
||||||
avatarLock.unlock();
|
});
|
||||||
}
|
|
||||||
void AvatarData::startCapture() {
|
|
||||||
avatarLock.lock();
|
|
||||||
assert(_nextAllowed);
|
|
||||||
_nextAllowed = false;
|
|
||||||
_nextPosition = getPosition();
|
|
||||||
_nextOrientation = getOrientation();
|
|
||||||
}
|
|
||||||
void AvatarData::endCapture() {
|
|
||||||
avatarLock.unlock();
|
|
||||||
}
|
|
||||||
void AvatarData::startUpdate() {
|
|
||||||
avatarLock.lock();
|
|
||||||
}
|
|
||||||
void AvatarData::endUpdate() {
|
|
||||||
avatarLock.unlock();
|
|
||||||
}
|
|
||||||
void AvatarData::startRenderRun() {
|
|
||||||
// I'd like to get rid of this and just (un)lock at (end-)startRender.
|
|
||||||
// But somehow that causes judder in rotations.
|
|
||||||
avatarLock.lock();
|
|
||||||
}
|
|
||||||
void AvatarData::endRenderRun() {
|
|
||||||
avatarLock.unlock();
|
|
||||||
}
|
|
||||||
void AvatarData::startRender() {
|
|
||||||
glm::vec3 pos = getPosition();
|
|
||||||
glm::quat rot = getOrientation();
|
|
||||||
setPosition(_nextPosition);
|
|
||||||
setOrientation(_nextOrientation);
|
|
||||||
updateAttitude();
|
updateAttitude();
|
||||||
_nextPosition = pos;
|
|
||||||
_nextOrientation = rot;
|
|
||||||
}
|
|
||||||
void AvatarData::endRender() {
|
|
||||||
setPosition(_nextPosition);
|
|
||||||
setOrientation(_nextOrientation);
|
|
||||||
updateAttitude();
|
|
||||||
_nextAllowed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float AvatarData::getTargetScale() const {
|
float AvatarData::getTargetScale() const {
|
||||||
|
|
|
@ -44,13 +44,13 @@ typedef unsigned long long quint64;
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QtScript/QScriptable>
|
#include <QtScript/QScriptable>
|
||||||
#include <QReadWriteLock>
|
|
||||||
|
|
||||||
#include <NLPacket.h>
|
#include <NLPacket.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <SimpleMovingAverage.h>
|
#include <SimpleMovingAverage.h>
|
||||||
#include <SpatiallyNestable.h>
|
#include <SpatiallyNestable.h>
|
||||||
|
#include <shared/ReadWriteLockable.h>
|
||||||
|
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
#include "HandData.h"
|
#include "HandData.h"
|
||||||
|
@ -59,6 +59,7 @@ typedef unsigned long long quint64;
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "Recorder.h"
|
#include "Recorder.h"
|
||||||
|
|
||||||
|
|
||||||
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
|
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
|
||||||
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
|
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
|
||||||
using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
|
using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
|
||||||
|
@ -135,7 +136,7 @@ class QDataStream;
|
||||||
class AttachmentData;
|
class AttachmentData;
|
||||||
class JointData;
|
class JointData;
|
||||||
|
|
||||||
class AvatarData : public QObject, public SpatiallyNestable {
|
class AvatarData : public QObject, public ReadWriteLockable, public SpatiallyNestable {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
||||||
|
@ -195,15 +196,10 @@ public:
|
||||||
float getBodyRoll() const;
|
float getBodyRoll() const;
|
||||||
void setBodyRoll(float bodyRoll);
|
void setBodyRoll(float bodyRoll);
|
||||||
|
|
||||||
|
virtual void setPosition(const glm::vec3& position);
|
||||||
|
virtual void setOrientation(const glm::quat& orientation);
|
||||||
|
|
||||||
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
||||||
void startCapture(); // start/end of the period in which the latest values are about to be captured for camera, etc.
|
|
||||||
void endCapture();
|
|
||||||
void startUpdate(); // start/end of update iteration
|
|
||||||
void endUpdate();
|
|
||||||
void startRender(); // start/end of rendering of this object
|
|
||||||
void startRenderRun(); // start/end of entire scene.
|
|
||||||
void endRenderRun();
|
|
||||||
void endRender();
|
|
||||||
virtual void updateAttitude() {} // Tell skeleton mesh about changes
|
virtual void updateAttitude() {} // Tell skeleton mesh about changes
|
||||||
|
|
||||||
glm::quat getHeadOrientation() const { return _headData->getOrientation(); }
|
glm::quat getHeadOrientation() const { return _headData->getOrientation(); }
|
||||||
|
@ -360,10 +356,6 @@ protected:
|
||||||
QUuid _sessionUUID;
|
QUuid _sessionUUID;
|
||||||
glm::vec3 _handPosition;
|
glm::vec3 _handPosition;
|
||||||
|
|
||||||
glm::vec3 _nextPosition {};
|
|
||||||
glm::quat _nextOrientation {};
|
|
||||||
bool _nextAllowed {true};
|
|
||||||
|
|
||||||
// Body scale
|
// Body scale
|
||||||
float _targetScale;
|
float _targetScale;
|
||||||
|
|
||||||
|
@ -413,8 +405,6 @@ protected:
|
||||||
|
|
||||||
SimpleMovingAverage _averageBytesReceived;
|
SimpleMovingAverage _averageBytesReceived;
|
||||||
|
|
||||||
QMutex avatarLock; // Name is redundant, but it aids searches.
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QUrl _defaultFullAvatarModelUrl;
|
static QUrl _defaultFullAvatarModelUrl;
|
||||||
// privatize the copy constructor and assignment operator so they cannot be called
|
// privatize the copy constructor and assignment operator so they cannot be called
|
||||||
|
|
|
@ -39,9 +39,14 @@ namespace render {
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex) :
|
MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex,
|
||||||
model(model), meshIndex(meshIndex), partIndex(partIndex), _shapeID(shapeIndex)
|
glm::vec3 position, glm::quat orientation) :
|
||||||
{
|
model(model),
|
||||||
|
meshIndex(meshIndex),
|
||||||
|
partIndex(partIndex),
|
||||||
|
_shapeID(shapeIndex),
|
||||||
|
_modelPosition(position),
|
||||||
|
_modelOrientation(orientation) {
|
||||||
initCache();
|
initCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +71,11 @@ void MeshPartPayload::initCache() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) {
|
||||||
|
_modelPosition = position;
|
||||||
|
_modelOrientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
render::ItemKey MeshPartPayload::getKey() const {
|
render::ItemKey MeshPartPayload::getKey() const {
|
||||||
ItemKey::Builder builder;
|
ItemKey::Builder builder;
|
||||||
builder.withTypeShape();
|
builder.withTypeShape();
|
||||||
|
@ -91,7 +101,7 @@ render::ItemKey MeshPartPayload::getKey() const {
|
||||||
render::Item::Bound MeshPartPayload::getBound() const {
|
render::Item::Bound MeshPartPayload::getBound() const {
|
||||||
// NOTE: we can't cache this bounds because we need to handle the case of a moving
|
// NOTE: we can't cache this bounds because we need to handle the case of a moving
|
||||||
// entity or mesh part.
|
// entity or mesh part.
|
||||||
return model->getPartBounds(meshIndex, partIndex);
|
return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPartPayload::drawCall(gpu::Batch& batch) const {
|
void MeshPartPayload::drawCall(gpu::Batch& batch) const {
|
||||||
|
@ -222,7 +232,7 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati
|
||||||
transform = Transform(state.clusterMatrices[0]);
|
transform = Transform(state.clusterMatrices[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transform.preTranslate(model->_translation);
|
transform.preTranslate(_modelPosition);
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +257,7 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back to model to update the cluster matrices right now
|
// Back to model to update the cluster matrices right now
|
||||||
model->updateClusterMatrices();
|
model->updateClusterMatrices(_modelPosition, _modelOrientation);
|
||||||
|
|
||||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Model;
|
||||||
|
|
||||||
class MeshPartPayload {
|
class MeshPartPayload {
|
||||||
public:
|
public:
|
||||||
MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex);
|
MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation);
|
||||||
|
|
||||||
typedef render::Payload<MeshPartPayload> Payload;
|
typedef render::Payload<MeshPartPayload> Payload;
|
||||||
typedef Payload::DataPointer Pointer;
|
typedef Payload::DataPointer Pointer;
|
||||||
|
@ -33,7 +33,11 @@ public:
|
||||||
int meshIndex;
|
int meshIndex;
|
||||||
int partIndex;
|
int partIndex;
|
||||||
int _shapeID;
|
int _shapeID;
|
||||||
|
glm::vec3 _modelPosition;
|
||||||
|
glm::quat _modelOrientation;
|
||||||
|
|
||||||
|
void updateModelLocation(glm::vec3 position, glm::quat orientation);
|
||||||
|
|
||||||
// Render Item interface
|
// Render Item interface
|
||||||
render::ItemKey getKey() const;
|
render::ItemKey getKey() const;
|
||||||
render::Item::Bound getBound() const;
|
render::Item::Bound getBound() const;
|
||||||
|
@ -63,4 +67,4 @@ namespace render {
|
||||||
template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args);
|
template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_MeshPartPayload_h
|
#endif // hifi_MeshPartPayload_h
|
||||||
|
|
|
@ -73,13 +73,16 @@ Model::~Model() {
|
||||||
|
|
||||||
AbstractViewStateInterface* Model::_viewState = NULL;
|
AbstractViewStateInterface* Model::_viewState = NULL;
|
||||||
|
|
||||||
|
|
||||||
void Model::setTranslation(const glm::vec3& translation) {
|
void Model::setTranslation(const glm::vec3& translation) {
|
||||||
_translation = translation;
|
_translation = translation;
|
||||||
|
enqueueLocationChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::setRotation(const glm::quat& rotation) {
|
void Model::setRotation(const glm::quat& rotation) {
|
||||||
_rotation = rotation;
|
_rotation = rotation;
|
||||||
}
|
enqueueLocationChange();
|
||||||
|
}
|
||||||
|
|
||||||
void Model::setScale(const glm::vec3& scale) {
|
void Model::setScale(const glm::vec3& scale) {
|
||||||
setScaleInternal(scale);
|
setScaleInternal(scale);
|
||||||
|
@ -107,6 +110,20 @@ void Model::setOffset(const glm::vec3& offset) {
|
||||||
_snappedToRegistrationPoint = false;
|
_snappedToRegistrationPoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::enqueueLocationChange() {
|
||||||
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
|
|
||||||
|
render::PendingChanges pendingChanges;
|
||||||
|
foreach (auto itemID, _renderItems.keys()) {
|
||||||
|
pendingChanges.updateItem<MeshPartPayload>(itemID, [=](MeshPartPayload& data) {
|
||||||
|
data.updateModelLocation(_translation, _rotation);
|
||||||
|
data.model->_needsUpdateClusterMatrices = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
}
|
||||||
|
|
||||||
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
||||||
QVector<JointState> jointStates;
|
QVector<JointState> jointStates;
|
||||||
for (int i = 0; i < geometry.joints.size(); ++i) {
|
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||||
|
@ -378,7 +395,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
_calculatedMeshPartBoxes.clear();
|
_calculatedMeshPartBoxes.clear();
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation);
|
||||||
|
|
||||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||||
|
|
||||||
|
@ -659,7 +676,8 @@ Extents Model::getUnscaledMeshExtents() const {
|
||||||
return scaledExtents;
|
return scaledExtents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
Extents Model::calculateScaledOffsetExtents(const Extents& extents,
|
||||||
|
glm::vec3 modelPosition, glm::quat modelOrientation) const {
|
||||||
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
||||||
glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
|
glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
|
||||||
glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
|
glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
|
||||||
|
@ -667,17 +685,17 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
||||||
Extents scaledOffsetExtents = { ((minimum + _offset) * _scale),
|
Extents scaledOffsetExtents = { ((minimum + _offset) * _scale),
|
||||||
((maximum + _offset) * _scale) };
|
((maximum + _offset) * _scale) };
|
||||||
|
|
||||||
Extents rotatedExtents = scaledOffsetExtents.getRotated(_rotation);
|
Extents rotatedExtents = scaledOffsetExtents.getRotated(modelOrientation);
|
||||||
|
|
||||||
Extents translatedExtents = { rotatedExtents.minimum + _translation,
|
Extents translatedExtents = { rotatedExtents.minimum + modelPosition,
|
||||||
rotatedExtents.maximum + _translation };
|
rotatedExtents.maximum + modelPosition };
|
||||||
|
|
||||||
return translatedExtents;
|
return translatedExtents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the world space equivalent of some box in model space.
|
/// Returns the world space equivalent of some box in model space.
|
||||||
AABox Model::calculateScaledOffsetAABox(const AABox& box) const {
|
AABox Model::calculateScaledOffsetAABox(const AABox& box, glm::vec3 modelPosition, glm::quat modelOrientation) const {
|
||||||
return AABox(calculateScaledOffsetExtents(Extents(box)));
|
return AABox(calculateScaledOffsetExtents(Extents(box), modelPosition, modelOrientation));
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const {
|
glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const {
|
||||||
|
@ -971,7 +989,7 @@ void Model::simulateInternal(float deltaTime) {
|
||||||
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||||
updateRig(deltaTime, parentTransform);
|
updateRig(deltaTime, parentTransform);
|
||||||
}
|
}
|
||||||
void Model::updateClusterMatrices() {
|
void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||||
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
||||||
|
|
||||||
if (!_needsUpdateClusterMatrices) {
|
if (!_needsUpdateClusterMatrices) {
|
||||||
|
@ -985,7 +1003,7 @@ void Model::updateClusterMatrices() {
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
|
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
|
||||||
|
|
||||||
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
|
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
|
||||||
for (int i = 0; i < _meshStates.size(); i++) {
|
for (int i = 0; i < _meshStates.size(); i++) {
|
||||||
MeshState& state = _meshStates[i];
|
MeshState& state = _meshStates[i];
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
@ -1007,16 +1025,21 @@ void Model::updateClusterMatrices() {
|
||||||
// Once computed the cluster matrices, update the buffer(s)
|
// Once computed the cluster matrices, update the buffer(s)
|
||||||
if (mesh.clusters.size() > 1) {
|
if (mesh.clusters.size() > 1) {
|
||||||
if (!state.clusterBuffer) {
|
if (!state.clusterBuffer) {
|
||||||
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
|
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||||
|
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||||
} else {
|
} else {
|
||||||
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
|
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||||
|
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {
|
if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {
|
||||||
if (!state.cauterizedClusterBuffer) {
|
if (!state.cauterizedClusterBuffer) {
|
||||||
state.cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
state.cauterizedClusterBuffer =
|
||||||
|
std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
||||||
|
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||||
} else {
|
} else {
|
||||||
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
||||||
|
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1109,7 +1132,7 @@ void Model::deleteGeometry() {
|
||||||
_blendedBlendshapeCoefficients.clear();
|
_blendedBlendshapeCoefficients.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||||
|
|
||||||
if (!_geometry || !_geometry->isLoaded()) {
|
if (!_geometry || !_geometry->isLoaded()) {
|
||||||
return AABox();
|
return AABox();
|
||||||
|
@ -1120,7 +1143,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
bool isSkinned = state.clusterMatrices.size() > 1;
|
bool isSkinned = state.clusterMatrices.size() > 1;
|
||||||
if (isSkinned) {
|
if (isSkinned) {
|
||||||
// if we're skinned return the entire mesh extents because we can't know for sure our clusters don't move us
|
// if we're skinned return the entire mesh extents because we can't know for sure our clusters don't move us
|
||||||
return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents);
|
return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents, modelPosition, modelOrientation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_geometry->getFBXGeometry().meshes.size() > meshIndex) {
|
if (_geometry->getFBXGeometry().meshes.size() > meshIndex) {
|
||||||
|
@ -1138,7 +1161,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
//
|
//
|
||||||
// If we not skinned use the bounds of the subMesh for all it's parts
|
// If we not skinned use the bounds of the subMesh for all it's parts
|
||||||
const FBXMesh& mesh = _geometry->getFBXGeometry().meshes.at(meshIndex);
|
const FBXMesh& mesh = _geometry->getFBXGeometry().meshes.at(meshIndex);
|
||||||
return calculateScaledOffsetExtents(mesh.meshExtents);
|
return calculateScaledOffsetExtents(mesh.meshExtents, modelPosition, modelOrientation);
|
||||||
}
|
}
|
||||||
return AABox();
|
return AABox();
|
||||||
}
|
}
|
||||||
|
@ -1164,7 +1187,7 @@ void Model::segregateMeshGroups() {
|
||||||
// Create the render payloads
|
// Create the render payloads
|
||||||
int totalParts = mesh.parts.size();
|
int totalParts = mesh.parts.size();
|
||||||
for (int partIndex = 0; partIndex < totalParts; partIndex++) {
|
for (int partIndex = 0; partIndex < totalParts; partIndex++) {
|
||||||
_renderItemsSet << std::make_shared<MeshPartPayload>(this, i, partIndex, shapeID);
|
_renderItemsSet << std::make_shared<MeshPartPayload>(this, i, partIndex, shapeID, _translation, _rotation);
|
||||||
shapeID++;
|
shapeID++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1184,6 +1207,7 @@ bool Model::initWhenReady(render::ScenePointer scene) {
|
||||||
_renderItems.insert(item, renderPayload);
|
_renderItems.insert(item, renderPayload);
|
||||||
pendingChanges.resetItem(item, renderPayload);
|
pendingChanges.resetItem(item, renderPayload);
|
||||||
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
||||||
|
data.updateModelLocation(_translation, _rotation);
|
||||||
data.model->_needsUpdateClusterMatrices = true;
|
data.model->_needsUpdateClusterMatrices = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,8 @@ public:
|
||||||
|
|
||||||
bool isVisible() const { return _isVisible; }
|
bool isVisible() const { return _isVisible; }
|
||||||
|
|
||||||
AABox getPartBounds(int meshIndex, int partIndex);
|
void updateRenderItems();
|
||||||
|
AABox getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||||
|
|
||||||
bool maybeStartBlender();
|
bool maybeStartBlender();
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ public:
|
||||||
bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; }
|
bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; }
|
||||||
|
|
||||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||||
void updateClusterMatrices();
|
void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||||
|
|
||||||
/// Returns a reference to the shared geometry.
|
/// Returns a reference to the shared geometry.
|
||||||
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
|
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
|
||||||
|
@ -183,6 +184,8 @@ public:
|
||||||
void setScale(const glm::vec3& scale);
|
void setScale(const glm::vec3& scale);
|
||||||
const glm::vec3& getScale() const { return _scale; }
|
const glm::vec3& getScale() const { return _scale; }
|
||||||
|
|
||||||
|
void enqueueLocationChange();
|
||||||
|
|
||||||
/// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension
|
/// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension
|
||||||
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
|
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
|
||||||
const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to
|
const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to
|
||||||
|
@ -210,10 +213,10 @@ protected:
|
||||||
Extents getUnscaledMeshExtents() const;
|
Extents getUnscaledMeshExtents() const;
|
||||||
|
|
||||||
/// Returns the scaled equivalent of some extents in model space.
|
/// Returns the scaled equivalent of some extents in model space.
|
||||||
Extents calculateScaledOffsetExtents(const Extents& extents) const;
|
Extents calculateScaledOffsetExtents(const Extents& extents, glm::vec3 modelPosition, glm::quat modelOrientation) const;
|
||||||
|
|
||||||
/// Returns the world space equivalent of some box in model space.
|
/// Returns the world space equivalent of some box in model space.
|
||||||
AABox calculateScaledOffsetAABox(const AABox& box) const;
|
AABox calculateScaledOffsetAABox(const AABox& box, glm::vec3 modelPosition, glm::quat modelOrientation) const;
|
||||||
|
|
||||||
/// Returns the scaled equivalent of a point in model space.
|
/// Returns the scaled equivalent of a point in model space.
|
||||||
glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const;
|
glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const;
|
||||||
|
|
Loading…
Reference in a new issue