Merge pull request #4384 from ctrlaltdavid/20369

CR for Job #20369 - Uploaded avatars without skeletons crash Interface
This commit is contained in:
Brad Hefta-Gaub 2015-03-08 11:42:07 -07:00
commit e2a367607a
6 changed files with 57 additions and 3 deletions

View file

@ -490,6 +490,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)),
bandwidthRecorder.data(), SLOT(updateInboundData(const quint8, const int)));
connect(&_myAvatar->getSkeletonModel(), &SkeletonModel::skeletonLoaded,
this, &Application::checkSkeleton, Qt::QueuedConnection);
// check first run...
if (_firstRun.get()) {
qDebug() << "This is a first run...";
@ -4044,3 +4047,19 @@ void Application::notifyPacketVersionMismatch() {
msgBox.exec();
}
}
void Application::checkSkeleton() {
if (_myAvatar->getSkeletonModel().isActive() && !_myAvatar->getSkeletonModel().hasSkeleton()) {
qDebug() << "MyAvatar model has no skeleton";
QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded...";
QMessageBox msgBox;
msgBox.setText(message);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
_myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL);
_myAvatar->sendIdentityPacket();
}
}

View file

@ -585,6 +585,8 @@ private:
QTimer _settingsTimer;
GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features
void checkSkeleton();
};
#endif // hifi_Application_h

View file

@ -177,6 +177,22 @@ bool ModelUploader::zip() {
}
QByteArray fbxContents = fbx.readAll();
FBXGeometry geometry = readFBX(fbxContents, QVariantHash());
// Make sure that a skeleton model has a skeleton
if (_modelType == SKELETON_MODEL) {
if (geometry.rootJointIndex == -1) {
QString message = "Your selected skeleton model has no skeleton.\n\nThe upload will be canceled.";
QMessageBox msgBox;
msgBox.setWindowTitle("Model Upload");
msgBox.setText(message);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
return false;
}
}
// make sure we have some basic mappings
populateBasicMapping(mapping, filename, geometry);

View file

@ -12,7 +12,6 @@
#include <algorithm>
#include <vector>
#include <QMessageBox>
#include <QBuffer>
#include <glm/gtx/norm.hpp>
@ -195,6 +194,12 @@ void MyAvatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("skeleton");
_skeletonModel.simulate(deltaTime);
}
if (!_skeletonModel.hasSkeleton()) {
// All the simulation that can be done has been done
return;
}
{
PerformanceTimer perfTimer("attachments");
simulateAttachments(deltaTime);

View file

@ -81,6 +81,8 @@ void SkeletonModel::setJointStates(QVector<JointState> states) {
if (_enableShapes) {
buildShapes();
}
emit skeletonLoaded();
}
const float PALM_PRIORITY = DEFAULT_PRIORITY;
@ -721,7 +723,8 @@ void SkeletonModel::buildShapes() {
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
if (geometry.joints.isEmpty()) {
if (geometry.joints.isEmpty() || geometry.rootJointIndex == -1) {
// rootJointIndex == -1 if the avatar model has no skeleton
return;
}
@ -1006,3 +1009,6 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) {
glPopMatrix();
}
bool SkeletonModel::hasSkeleton() {
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
}

View file

@ -123,7 +123,13 @@ public:
void resetShapePositionsToDefaultPose(); // DEBUG method
void renderRagdoll();
bool hasSkeleton();
signals:
void skeletonLoaded();
protected:
void buildShapes();