mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 08:17:35 +02:00
The basic billboard behavior, closes #1864.
This commit is contained in:
parent
8d01527d93
commit
ac02609bc2
14 changed files with 146 additions and 19 deletions
|
@ -123,15 +123,22 @@ void broadcastIdentityPacket() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void broadcastBillboardPacket(const SharedNodePointer& node) {
|
void broadcastBillboardPacket(const SharedNodePointer& sendingNode) {
|
||||||
|
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(sendingNode->getLinkedData());
|
||||||
|
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
|
||||||
|
packet.append(sendingNode->getUUID().toRfc4122());
|
||||||
|
packet.append(nodeData->getBillboard());
|
||||||
|
|
||||||
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||||
|
if (node->getType() == NodeType::Agent && node != sendingNode) {
|
||||||
|
nodeList->writeDatagram(packet, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void broadcastBillboardPackets() {
|
void broadcastBillboardPackets() {
|
||||||
|
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
|
||||||
|
|
||||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
|
||||||
if (node->getLinkedData() && node->getType() == NodeType::Agent) {
|
if (node->getLinkedData() && node->getType() == NodeType::Agent) {
|
||||||
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(node->getLinkedData());
|
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(node->getLinkedData());
|
||||||
broadcastBillboardPacket(node);
|
broadcastBillboardPacket(node);
|
||||||
|
|
|
@ -98,6 +98,7 @@ const int MIRROR_VIEW_HEIGHT = 215;
|
||||||
const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
|
const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
|
||||||
const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
||||||
const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
||||||
|
const float MIRROR_FIELD_OF_VIEW = 30.0f;
|
||||||
|
|
||||||
const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml";
|
const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml";
|
||||||
const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
|
const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
|
||||||
|
@ -2688,7 +2689,7 @@ QImage Application::renderAvatarBillboard() {
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
const int BILLBOARD_SIZE = 128;
|
const int BILLBOARD_SIZE = 64;
|
||||||
renderRearViewMirror(QRect(0, _glWidget->height() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
|
renderRearViewMirror(QRect(0, _glWidget->height() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
|
||||||
|
|
||||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||||
|
@ -3621,13 +3622,17 @@ void Application::renderCoverageMapsRecursively(CoverageMap* map) {
|
||||||
void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||||
bool eyeRelativeCamera = false;
|
bool eyeRelativeCamera = false;
|
||||||
if (billboard) {
|
if (billboard) {
|
||||||
const float BILLBOARD_DISTANCE = 5.0f;
|
_mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW);
|
||||||
_mirrorCamera.setDistance(BILLBOARD_DISTANCE * _myAvatar->getScale());
|
_mirrorCamera.setDistance(BILLBOARD_DISTANCE * _myAvatar->getScale());
|
||||||
_mirrorCamera.setTargetPosition(_myAvatar->getPosition());
|
_mirrorCamera.setTargetPosition(_myAvatar->getPosition());
|
||||||
|
|
||||||
} else if (_rearMirrorTools->getZoomLevel() == BODY) {
|
} else if (_rearMirrorTools->getZoomLevel() == BODY) {
|
||||||
|
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW);
|
||||||
_mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
|
_mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
|
||||||
_mirrorCamera.setTargetPosition(_myAvatar->getChestPosition());
|
_mirrorCamera.setTargetPosition(_myAvatar->getChestPosition());
|
||||||
|
|
||||||
} else { // HEAD zoom level
|
} else { // HEAD zoom level
|
||||||
|
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW);
|
||||||
_mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
_mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||||
if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead()->getFaceModel().isActive()) {
|
if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead()->getFaceModel().isActive()) {
|
||||||
// as a hack until we have a better way of dealing with coordinate precision issues, reposition the
|
// as a hack until we have a better way of dealing with coordinate precision issues, reposition the
|
||||||
|
@ -3639,7 +3644,8 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||||
_mirrorCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
_mirrorCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_mirrorCamera.setAspectRatio((float)region.width() / region.height());
|
||||||
|
|
||||||
_mirrorCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f)));
|
_mirrorCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f)));
|
||||||
_mirrorCamera.update(1.0f/_fps);
|
_mirrorCamera.update(1.0f/_fps);
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,9 @@ static const float NODE_KILLED_BLUE = 0.0f;
|
||||||
|
|
||||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||||
|
|
||||||
|
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f;
|
||||||
|
static const float BILLBOARD_DISTANCE = 5.0f;
|
||||||
|
|
||||||
class Application : public QApplication {
|
class Application : public QApplication {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,8 @@ void DatagramProcessor::processDatagrams() {
|
||||||
break;
|
break;
|
||||||
case PacketTypeBulkAvatarData:
|
case PacketTypeBulkAvatarData:
|
||||||
case PacketTypeKillAvatar:
|
case PacketTypeKillAvatar:
|
||||||
case PacketTypeAvatarIdentity: {
|
case PacketTypeAvatarIdentity:
|
||||||
|
case PacketTypeAvatarBillboard: {
|
||||||
// update having heard from the avatar-mixer and record the bytes received
|
// update having heard from the avatar-mixer and record the bytes received
|
||||||
SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket);
|
SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Physics.h"
|
#include "Physics.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "devices/OculusManager.h"
|
#include "devices/OculusManager.h"
|
||||||
|
#include "renderer/TextureCache.h"
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -107,6 +108,10 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
|
||||||
return computeRotationFromBodyToWorldUp() * getOrientation();
|
return computeRotationFromBodyToWorldUp() * getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Avatar::getLODDistance() const {
|
||||||
|
return glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::simulate(float deltaTime) {
|
void Avatar::simulate(float deltaTime) {
|
||||||
if (_scale != _targetScale) {
|
if (_scale != _targetScale) {
|
||||||
setScale(_targetScale);
|
setScale(_targetScale);
|
||||||
|
@ -116,6 +121,7 @@ void Avatar::simulate(float deltaTime) {
|
||||||
glm::vec3 oldVelocity = getVelocity();
|
glm::vec3 oldVelocity = getVelocity();
|
||||||
|
|
||||||
getHand()->simulate(deltaTime, false);
|
getHand()->simulate(deltaTime, false);
|
||||||
|
_skeletonModel.setLODDistance(getLODDistance());
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
|
@ -282,9 +288,11 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::renderBody(bool forceRenderHead) {
|
void Avatar::renderBody(bool forceRenderHead) {
|
||||||
// Render the body's voxels and head
|
const float BILLBOARD_DISTANCE = 40.0f;
|
||||||
glm::vec3 pos = getPosition();
|
if (!_billboard.isEmpty() && getLODDistance() >= BILLBOARD_DISTANCE) {
|
||||||
//printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z);
|
renderBillboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
_skeletonModel.render(1.0f);
|
_skeletonModel.render(1.0f);
|
||||||
if (forceRenderHead) {
|
if (forceRenderHead) {
|
||||||
getHead()->render(1.0f);
|
getHead()->render(1.0f);
|
||||||
|
@ -292,6 +300,62 @@ void Avatar::renderBody(bool forceRenderHead) {
|
||||||
getHand()->render(false);
|
getHand()->render(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::renderBillboard() {
|
||||||
|
if (!_billboardTexture) {
|
||||||
|
QImage image = QImage::fromData(_billboard).convertToFormat(QImage::Format_ARGB32);
|
||||||
|
|
||||||
|
_billboardTexture.reset(new Texture());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 1,
|
||||||
|
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_ALPHA_TEST);
|
||||||
|
glAlphaFunc(GL_GREATER, 0.5f);
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(_position.x, _position.y, _position.z);
|
||||||
|
|
||||||
|
// rotate about vertical to face the camera
|
||||||
|
glm::quat rotation = getOrientation();
|
||||||
|
glm::vec3 cameraVector = glm::inverse(rotation) * (Application::getInstance()->getCamera()->getPosition() - _position);
|
||||||
|
rotation = rotation * glm::angleAxis(glm::degrees(atan2f(-cameraVector.x, -cameraVector.z)), 0.0f, 1.0f, 0.0f);
|
||||||
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
|
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
|
// compute the size from the billboard camera parameters and scale
|
||||||
|
float size = _scale * BILLBOARD_DISTANCE * tanf(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||||
|
glScalef(size, size, size);
|
||||||
|
|
||||||
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex2f(-1.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex2f(1.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex2f(1.0f, 1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex2f(-1.0f, 1.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::renderDisplayName() {
|
void Avatar::renderDisplayName() {
|
||||||
|
|
||||||
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
||||||
|
@ -502,6 +566,13 @@ void Avatar::setDisplayName(const QString& displayName) {
|
||||||
_displayNameBoundingRect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(displayName);
|
_displayNameBoundingRect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::setBillboard(const QByteArray& billboard) {
|
||||||
|
AvatarData::setBillboard(billboard);
|
||||||
|
|
||||||
|
// clear out any existing billboard texture
|
||||||
|
_billboardTexture.reset();
|
||||||
|
}
|
||||||
|
|
||||||
int Avatar::parseData(const QByteArray& packet) {
|
int Avatar::parseData(const QByteArray& packet) {
|
||||||
// change in position implies movement
|
// change in position implies movement
|
||||||
glm::vec3 oldPosition = _position;
|
glm::vec3 oldPosition = _position;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
#include <QtCore/QScopedPointer>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
|
@ -62,6 +63,8 @@ enum ScreenTintLayer {
|
||||||
// Grayson as he's building a street around here for demo dinner 2
|
// Grayson as he's building a street around here for demo dinner 2
|
||||||
const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE);
|
const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE);
|
||||||
|
|
||||||
|
class Texture;
|
||||||
|
|
||||||
class Avatar : public AvatarData {
|
class Avatar : public AvatarData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -87,6 +90,9 @@ public:
|
||||||
Head* getHead() { return static_cast<Head*>(_headData); }
|
Head* getHead() { return static_cast<Head*>(_headData); }
|
||||||
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
||||||
glm::quat getWorldAlignedOrientation() const;
|
glm::quat getWorldAlignedOrientation() const;
|
||||||
|
|
||||||
|
/// Returns the distance to use as a LOD parameter.
|
||||||
|
float getLODDistance() const;
|
||||||
|
|
||||||
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
||||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||||
|
@ -114,6 +120,7 @@ public:
|
||||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||||
virtual void setDisplayName(const QString& displayName);
|
virtual void setDisplayName(const QString& displayName);
|
||||||
|
virtual void setBillboard(const QByteArray& billboard);
|
||||||
|
|
||||||
void setShowDisplayName(bool showDisplayName);
|
void setShowDisplayName(bool showDisplayName);
|
||||||
|
|
||||||
|
@ -167,8 +174,10 @@ protected:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
|
QScopedPointer<Texture> _billboardTexture;
|
||||||
|
|
||||||
void renderBody(bool forceRenderHead);
|
void renderBody(bool forceRenderHead);
|
||||||
|
void renderBillboard();
|
||||||
|
|
||||||
void renderDisplayName();
|
void renderDisplayName();
|
||||||
};
|
};
|
||||||
|
|
|
@ -133,6 +133,9 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
|
||||||
case PacketTypeAvatarIdentity:
|
case PacketTypeAvatarIdentity:
|
||||||
processAvatarIdentityPacket(datagram);
|
processAvatarIdentityPacket(datagram);
|
||||||
break;
|
break;
|
||||||
|
case PacketTypeAvatarBillboard:
|
||||||
|
processAvatarBillboardPacket(datagram);
|
||||||
|
break;
|
||||||
case PacketTypeKillAvatar:
|
case PacketTypeKillAvatar:
|
||||||
processKillAvatar(datagram);
|
processKillAvatar(datagram);
|
||||||
break;
|
break;
|
||||||
|
@ -212,6 +215,20 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarManager::processAvatarBillboardPacket(const QByteArray& packet) {
|
||||||
|
int headerSize = numBytesForPacketHeader(packet);
|
||||||
|
QUuid nodeUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
|
||||||
|
|
||||||
|
AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID);
|
||||||
|
if (matchingAvatar) {
|
||||||
|
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
|
||||||
|
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
|
||||||
|
if (avatar->getBillboard() != billboard) {
|
||||||
|
avatar->setBillboard(billboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AvatarManager::processKillAvatar(const QByteArray& datagram) {
|
void AvatarManager::processKillAvatar(const QByteArray& datagram) {
|
||||||
// read the node id
|
// read the node id
|
||||||
QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
|
QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
|
||||||
|
|
|
@ -42,6 +42,7 @@ private:
|
||||||
|
|
||||||
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||||
void processAvatarIdentityPacket(const QByteArray& packet);
|
void processAvatarIdentityPacket(const QByteArray& packet);
|
||||||
|
void processAvatarBillboardPacket(const QByteArray& packet);
|
||||||
void processKillAvatar(const QByteArray& datagram);
|
void processKillAvatar(const QByteArray& datagram);
|
||||||
|
|
||||||
void simulateAvatarFades(float deltaTime);
|
void simulateAvatarFades(float deltaTime);
|
||||||
|
|
|
@ -158,6 +158,9 @@ void Head::simulate(float deltaTime, bool isMine) {
|
||||||
glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) - JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients);
|
glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) - JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isMine) {
|
||||||
|
_faceModel.setLODDistance(static_cast<Avatar*>(_owningAvatar)->getLODDistance());
|
||||||
|
}
|
||||||
_faceModel.simulate(deltaTime);
|
_faceModel.simulate(deltaTime);
|
||||||
|
|
||||||
// the blend face may have custom eye meshes
|
// the blend face may have custom eye meshes
|
||||||
|
|
|
@ -1147,7 +1147,7 @@ void MyAvatar::maybeUpdateBillboard() {
|
||||||
_billboard.clear();
|
_billboard.clear();
|
||||||
QBuffer buffer(&_billboard);
|
QBuffer buffer(&_billboard);
|
||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
image.save(&buffer, "JPG");
|
image.save(&buffer, "PNG");
|
||||||
_billboardValid = true;
|
_billboardValid = true;
|
||||||
|
|
||||||
sendBillboardPacket();
|
sendBillboardPacket();
|
||||||
|
|
|
@ -17,8 +17,8 @@ using namespace std;
|
||||||
|
|
||||||
Model::Model(QObject* parent) :
|
Model::Model(QObject* parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
_pupilDilation(0.0f)
|
_lodDistance(0.0f),
|
||||||
{
|
_pupilDilation(0.0f) {
|
||||||
// we may have been created in the network thread, but we live in the main thread
|
// we may have been created in the network thread, but we live in the main thread
|
||||||
moveToThread(Application::getInstance()->thread());
|
moveToThread(Application::getInstance()->thread());
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,7 @@ void Model::reset() {
|
||||||
void Model::simulate(float deltaTime) {
|
void Model::simulate(float deltaTime) {
|
||||||
// update our LOD
|
// update our LOD
|
||||||
if (_geometry) {
|
if (_geometry) {
|
||||||
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(glm::distance(_translation,
|
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis);
|
||||||
Application::getInstance()->getCamera()->getPosition()), _lodHysteresis);
|
|
||||||
if (_geometry != geometry) {
|
if (_geometry != geometry) {
|
||||||
deleteGeometry();
|
deleteGeometry();
|
||||||
_dilatedTextures.clear();
|
_dilatedTextures.clear();
|
||||||
|
|
|
@ -56,6 +56,9 @@ public:
|
||||||
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl());
|
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl());
|
||||||
const QUrl& getURL() const { return _url; }
|
const QUrl& getURL() const { return _url; }
|
||||||
|
|
||||||
|
/// Sets the distance parameter used for LOD computations.
|
||||||
|
void setLODDistance(float distance) { _lodDistance = distance; }
|
||||||
|
|
||||||
/// Returns the extents of the model in its bind pose.
|
/// Returns the extents of the model in its bind pose.
|
||||||
Extents getBindExtents() const;
|
Extents getBindExtents() const;
|
||||||
|
|
||||||
|
@ -230,13 +233,14 @@ private:
|
||||||
void renderMeshes(float alpha, bool translucent);
|
void renderMeshes(float alpha, bool translucent);
|
||||||
|
|
||||||
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
||||||
|
float _lodDistance;
|
||||||
float _lodHysteresis;
|
float _lodHysteresis;
|
||||||
|
|
||||||
float _pupilDilation;
|
float _pupilDilation;
|
||||||
std::vector<float> _blendshapeCoefficients;
|
std::vector<float> _blendshapeCoefficients;
|
||||||
|
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
|
|
||||||
QVector<GLuint> _blendedVertexBufferIDs;
|
QVector<GLuint> _blendedVertexBufferIDs;
|
||||||
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
||||||
bool _resetStates;
|
bool _resetStates;
|
||||||
|
|
|
@ -332,6 +332,12 @@ void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
qDebug() << "Changing display name for avatar to" << displayName;
|
qDebug() << "Changing display name for avatar to" << displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarData::setBillboard(const QByteArray& billboard) {
|
||||||
|
_billboard = billboard;
|
||||||
|
|
||||||
|
qDebug() << "Changing billboard for avatar.";
|
||||||
|
}
|
||||||
|
|
||||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
void AvatarData::setClampedTargetScale(float targetScale) {
|
||||||
|
|
||||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||||
|
|
|
@ -163,7 +163,7 @@ public:
|
||||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||||
virtual void setDisplayName(const QString& displayName);
|
virtual void setDisplayName(const QString& displayName);
|
||||||
|
|
||||||
void setBillboard(const QByteArray& billboard) { _billboard = billboard; }
|
virtual void setBillboard(const QByteArray& billboard);
|
||||||
const QByteArray& getBillboard() const { return _billboard; }
|
const QByteArray& getBillboard() const { return _billboard; }
|
||||||
|
|
||||||
QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); }
|
QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); }
|
||||||
|
|
Loading…
Reference in a new issue