mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Interface only sends joint data to avatar-mixer if they have changed enough since the last send
This commit is contained in:
parent
3d7aa6f4d6
commit
76923583ee
8 changed files with 47 additions and 29 deletions
|
@ -295,7 +295,7 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
avatarPacketList.startSegment();
|
avatarPacketList.startSegment();
|
||||||
|
|
||||||
numAvatarDataBytes += avatarPacketList.write(otherNode->getUUID().toRfc4122());
|
numAvatarDataBytes += avatarPacketList.write(otherNode->getUUID().toRfc4122());
|
||||||
numAvatarDataBytes += avatarPacketList.write(otherAvatar.toByteArray());
|
numAvatarDataBytes += avatarPacketList.write(otherAvatar.toByteArray(false));
|
||||||
|
|
||||||
avatarPacketList.endSegment();
|
avatarPacketList.endSegment();
|
||||||
|
|
||||||
|
|
|
@ -77,10 +77,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
int mapping = animationJoints.indexOf(modelJoints[i]);
|
int mapping = animationJoints.indexOf(modelJoints[i]);
|
||||||
if (mapping != -1 && !_maskedJoints.contains(modelJoints[i])) {
|
if (mapping != -1 && !_maskedJoints.contains(modelJoints[i])) {
|
||||||
JointData& data = _jointData[i];
|
JointData& data = _jointData[i];
|
||||||
data.valid = true;
|
|
||||||
data.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
data.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||||
} else {
|
|
||||||
_jointData[i].valid = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -200,11 +200,9 @@ void Avatar::simulate(float deltaTime) {
|
||||||
if (!_shouldRenderBillboard && inViewFrustum) {
|
if (!_shouldRenderBillboard && inViewFrustum) {
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("skeleton");
|
PerformanceTimer perfTimer("skeleton");
|
||||||
if (_hasNewJointRotations) {
|
for (int i = 0; i < _jointData.size(); i++) {
|
||||||
for (int i = 0; i < _jointData.size(); i++) {
|
const JointData& data = _jointData.at(i);
|
||||||
const JointData& data = _jointData.at(i);
|
_skeletonModel.setJointState(i, true, data.rotation);
|
||||||
_skeletonModel.setJointState(i, data.valid, data.rotation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_skeletonModel.simulate(deltaTime, _hasNewJointRotations);
|
_skeletonModel.simulate(deltaTime, _hasNewJointRotations);
|
||||||
simulateAttachments(deltaTime);
|
simulateAttachments(deltaTime);
|
||||||
|
|
|
@ -123,18 +123,18 @@ MyAvatar::~MyAvatar() {
|
||||||
_lookAtTargetAvatar.reset();
|
_lookAtTargetAvatar.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray MyAvatar::toByteArray() {
|
QByteArray MyAvatar::toByteArray(bool cullSmallChanges) {
|
||||||
CameraMode mode = Application::getInstance()->getCamera()->getMode();
|
CameraMode mode = Application::getInstance()->getCamera()->getMode();
|
||||||
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
||||||
// fake the avatar position that is sent up to the AvatarMixer
|
// fake the avatar position that is sent up to the AvatarMixer
|
||||||
glm::vec3 oldPosition = _position;
|
glm::vec3 oldPosition = _position;
|
||||||
_position = getSkeletonPosition();
|
_position = getSkeletonPosition();
|
||||||
QByteArray array = AvatarData::toByteArray();
|
QByteArray array = AvatarData::toByteArray(cullSmallChanges);
|
||||||
// copy the correct position back
|
// copy the correct position back
|
||||||
_position = oldPosition;
|
_position = oldPosition;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
return AvatarData::toByteArray();
|
return AvatarData::toByteArray(cullSmallChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::reset() {
|
void MyAvatar::reset() {
|
||||||
|
@ -220,7 +220,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
_jointData.resize(_rig->getJointStateCount());
|
_jointData.resize(_rig->getJointStateCount());
|
||||||
for (int i = 0; i < _jointData.size(); i++) {
|
for (int i = 0; i < _jointData.size(); i++) {
|
||||||
JointData& data = _jointData[i];
|
JointData& data = _jointData[i];
|
||||||
data.valid = _rig->getJointStateRotation(i, data.rotation);
|
_rig->getJointStateRotation(i, data.rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ private:
|
||||||
|
|
||||||
glm::vec3 getWorldBodyPosition() const;
|
glm::vec3 getWorldBodyPosition() const;
|
||||||
glm::quat getWorldBodyOrientation() const;
|
glm::quat getWorldBodyOrientation() const;
|
||||||
QByteArray toByteArray();
|
QByteArray toByteArray(bool cullSmallChanges);
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
void updateFromTrackers(float deltaTime);
|
void updateFromTrackers(float deltaTime);
|
||||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
|
|
||||||
quint64 DEFAULT_FILTERED_LOG_EXPIRY = 2 * USECS_PER_SECOND;
|
quint64 DEFAULT_FILTERED_LOG_EXPIRY = 2 * USECS_PER_SECOND;
|
||||||
|
|
||||||
|
// this controls how large a change in joint-rotation must be before the interface sends it to the avatar mixer
|
||||||
|
const float MIN_ROTATION_DOT = 0.9999999f;
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const glm::vec3 DEFAULT_LOCAL_AABOX_CORNER(-0.5f);
|
const glm::vec3 DEFAULT_LOCAL_AABOX_CORNER(-0.5f);
|
||||||
|
@ -141,7 +145,7 @@ void AvatarData::setHandPosition(const glm::vec3& handPosition) {
|
||||||
_handPosition = glm::inverse(getOrientation()) * (handPosition - _position);
|
_handPosition = glm::inverse(getOrientation()) * (handPosition - _position);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray AvatarData::toByteArray() {
|
QByteArray AvatarData::toByteArray(bool cullSmallChanges) {
|
||||||
// TODO: DRY this up to a shared method
|
// TODO: DRY this up to a shared method
|
||||||
// that can pack any type given the number of bytes
|
// that can pack any type given the number of bytes
|
||||||
// and return the number of bytes to push the pointer
|
// and return the number of bytes to push the pointer
|
||||||
|
@ -234,11 +238,19 @@ QByteArray AvatarData::toByteArray() {
|
||||||
|
|
||||||
// joint data
|
// joint data
|
||||||
*destinationBuffer++ = _jointData.size();
|
*destinationBuffer++ = _jointData.size();
|
||||||
|
unsigned char* validityPosition = destinationBuffer;
|
||||||
unsigned char validity = 0;
|
unsigned char validity = 0;
|
||||||
int validityBit = 0;
|
int validityBit = 0;
|
||||||
foreach (const JointData& data, _jointData) {
|
|
||||||
if (data.valid) {
|
_lastSentJointData.resize(_jointData.size());
|
||||||
validity |= (1 << validityBit);
|
|
||||||
|
// foreach (const JointData& data, _jointData) {
|
||||||
|
for (int i=0; i < _jointData.size(); i++) {
|
||||||
|
const JointData& data = _jointData.at(i);
|
||||||
|
if (_lastSentJointData[i].rotation != data.rotation) {
|
||||||
|
if (!cullSmallChanges || fabsf(glm::dot(data.rotation, _lastSentJointData[i].rotation)) <= MIN_ROTATION_DOT) {
|
||||||
|
validity |= (1 << validityBit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (++validityBit == BITS_IN_BYTE) {
|
if (++validityBit == BITS_IN_BYTE) {
|
||||||
*destinationBuffer++ = validity;
|
*destinationBuffer++ = validity;
|
||||||
|
@ -248,9 +260,18 @@ QByteArray AvatarData::toByteArray() {
|
||||||
if (validityBit != 0) {
|
if (validityBit != 0) {
|
||||||
*destinationBuffer++ = validity;
|
*destinationBuffer++ = validity;
|
||||||
}
|
}
|
||||||
foreach (const JointData& data, _jointData) {
|
|
||||||
if (data.valid) {
|
validityBit = 0;
|
||||||
|
validity = *validityPosition++;
|
||||||
|
for (int i = 0; i < _jointData.size(); i ++) {
|
||||||
|
const JointData& data = _jointData[ i ];
|
||||||
|
if (validity & (1 << validityBit)) {
|
||||||
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, data.rotation);
|
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, data.rotation);
|
||||||
|
_lastSentJointData[i].rotation = data.rotation;
|
||||||
|
}
|
||||||
|
if (++validityBit == BITS_IN_BYTE) {
|
||||||
|
validityBit = 0;
|
||||||
|
validity = *validityPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +515,10 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
}
|
}
|
||||||
int numValidJoints = 0;
|
int numValidJoints = 0;
|
||||||
_jointData.resize(numJoints);
|
_jointData.resize(numJoints);
|
||||||
|
|
||||||
|
QVector<bool> valids;
|
||||||
|
valids.resize(numJoints);
|
||||||
|
|
||||||
{ // validity bits
|
{ // validity bits
|
||||||
unsigned char validity = 0;
|
unsigned char validity = 0;
|
||||||
int validityBit = 0;
|
int validityBit = 0;
|
||||||
|
@ -505,7 +530,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
++numValidJoints;
|
++numValidJoints;
|
||||||
}
|
}
|
||||||
_jointData[i].valid = valid;
|
valids[i] = valid;
|
||||||
validityBit = (validityBit + 1) % BITS_IN_BYTE;
|
validityBit = (validityBit + 1) % BITS_IN_BYTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +552,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
{ // joint data
|
{ // joint data
|
||||||
for (int i = 0; i < numJoints; i++) {
|
for (int i = 0; i < numJoints; i++) {
|
||||||
JointData& data = _jointData[i];
|
JointData& data = _jointData[i];
|
||||||
if (data.valid) {
|
if (valids[i]) {
|
||||||
_hasNewJointRotations = true;
|
_hasNewJointRotations = true;
|
||||||
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, data.rotation);
|
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, data.rotation);
|
||||||
}
|
}
|
||||||
|
@ -731,7 +756,6 @@ void AvatarData::setJointData(int index, const glm::quat& rotation) {
|
||||||
_jointData.resize(index + 1);
|
_jointData.resize(index + 1);
|
||||||
}
|
}
|
||||||
JointData& data = _jointData[index];
|
JointData& data = _jointData[index];
|
||||||
data.valid = true;
|
|
||||||
data.rotation = rotation;
|
data.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,7 +770,6 @@ void AvatarData::clearJointData(int index) {
|
||||||
if (_jointData.size() <= index) {
|
if (_jointData.size() <= index) {
|
||||||
_jointData.resize(index + 1);
|
_jointData.resize(index + 1);
|
||||||
}
|
}
|
||||||
_jointData[index].valid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvatarData::isJointDataValid(int index) const {
|
bool AvatarData::isJointDataValid(int index) const {
|
||||||
|
@ -759,7 +782,7 @@ bool AvatarData::isJointDataValid(int index) const {
|
||||||
Q_RETURN_ARG(bool, result), Q_ARG(int, index));
|
Q_RETURN_ARG(bool, result), Q_ARG(int, index));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return index < _jointData.size() && _jointData.at(index).valid;
|
return index < _jointData.size() /* && _jointData.at(index).valid */;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat AvatarData::getJointRotation(int index) const {
|
glm::quat AvatarData::getJointRotation(int index) const {
|
||||||
|
@ -1060,7 +1083,7 @@ void AvatarData::setJointMappingsFromNetworkReply() {
|
||||||
void AvatarData::sendAvatarDataPacket() {
|
void AvatarData::sendAvatarDataPacket() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
QByteArray avatarByteArray = toByteArray();
|
QByteArray avatarByteArray = toByteArray(true);
|
||||||
|
|
||||||
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size());
|
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size());
|
||||||
avatarPacket->write(avatarByteArray);
|
avatarPacket->write(avatarByteArray);
|
||||||
|
|
|
@ -171,7 +171,7 @@ public:
|
||||||
glm::vec3 getHandPosition() const;
|
glm::vec3 getHandPosition() const;
|
||||||
void setHandPosition(const glm::vec3& handPosition);
|
void setHandPosition(const glm::vec3& handPosition);
|
||||||
|
|
||||||
virtual QByteArray toByteArray();
|
virtual QByteArray toByteArray(bool cullSmallChanges);
|
||||||
|
|
||||||
/// \return true if an error should be logged
|
/// \return true if an error should be logged
|
||||||
bool shouldLogError(const quint64& now);
|
bool shouldLogError(const quint64& now);
|
||||||
|
@ -357,6 +357,7 @@ protected:
|
||||||
char _handState;
|
char _handState;
|
||||||
|
|
||||||
QVector<JointData> _jointData; ///< the state of the skeleton joints
|
QVector<JointData> _jointData; ///< the state of the skeleton joints
|
||||||
|
QVector<JointData> _lastSentJointData; ///< the state of the skeleton joints last time we transmitted
|
||||||
|
|
||||||
// key state
|
// key state
|
||||||
KeyState _keyState;
|
KeyState _keyState;
|
||||||
|
@ -408,7 +409,6 @@ Q_DECLARE_METATYPE(AvatarData*)
|
||||||
|
|
||||||
class JointData {
|
class JointData {
|
||||||
public:
|
public:
|
||||||
bool valid;
|
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -599,7 +599,7 @@ void ScriptEngine::run() {
|
||||||
/ (1000 * 1000)) + 0.5);
|
/ (1000 * 1000)) + 0.5);
|
||||||
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
|
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
|
||||||
|
|
||||||
QByteArray avatarByteArray = _avatarData->toByteArray();
|
QByteArray avatarByteArray = _avatarData->toByteArray(true);
|
||||||
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size());
|
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size());
|
||||||
|
|
||||||
avatarPacket->write(avatarByteArray);
|
avatarPacket->write(avatarByteArray);
|
||||||
|
|
Loading…
Reference in a new issue