mirror of
https://github.com/overte-org/overte.git
synced 2025-07-10 22:38:33 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
9ffd93a167
16 changed files with 121 additions and 183 deletions
|
@ -39,7 +39,7 @@ you to run the full stack of the virtual world.
|
||||||
In order to set up your own virtual world, you need to set up and run your own
|
In order to set up your own virtual world, you need to set up and run your own
|
||||||
local "domain".
|
local "domain".
|
||||||
|
|
||||||
The domain-server gives a number different types of assignments to the assignment-client for different features: audio, avatars, voxels, particles, and meta-voxels.
|
The domain-server gives a number different types of assignments to the assignment-client for different features: audio, avatars, voxels, particles, meta-voxels and models.
|
||||||
|
|
||||||
Follow the instructions in the [build guide](BUILD.md) to build the various components.
|
Follow the instructions in the [build guide](BUILD.md) to build the various components.
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ Any target can be terminated with Ctrl-C (SIGINT) in the associated Terminal win
|
||||||
|
|
||||||
This assignment-client will grab one assignment from the domain-server. You can tell the assignment-client what type you want it to be with the `-t` option. You can also run an assignment-client that forks off *n* assignment-clients with the `-n` option.
|
This assignment-client will grab one assignment from the domain-server. You can tell the assignment-client what type you want it to be with the `-t` option. You can also run an assignment-client that forks off *n* assignment-clients with the `-n` option.
|
||||||
|
|
||||||
./assignment-client -n 5
|
./assignment-client -n 6
|
||||||
|
|
||||||
To test things out you'll want to run the Interface client.
|
To test things out you'll want to run the Interface client.
|
||||||
|
|
||||||
|
|
|
@ -331,8 +331,9 @@ function ScaleSelector() {
|
||||||
});
|
});
|
||||||
this.setScale = function(scale) {
|
this.setScale = function(scale) {
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.power = Math.floor(Math.log(scale));
|
this.power = Math.floor(Math.log(scale) / Math.log(2));
|
||||||
rescaleImport();
|
rescaleImport();
|
||||||
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.show = function(doShow) {
|
this.show = function(doShow) {
|
||||||
|
@ -835,7 +836,6 @@ function showPreviewLines() {
|
||||||
|
|
||||||
if (copyScale) {
|
if (copyScale) {
|
||||||
scaleSelector.setScale(intersection.voxel.s);
|
scaleSelector.setScale(intersection.voxel.s);
|
||||||
scaleSelector.update();
|
|
||||||
}
|
}
|
||||||
moveTools();
|
moveTools();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -561,42 +561,6 @@ void Application::paintGL() {
|
||||||
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
|
|
||||||
glm::vec3 planeNormal = _myCamera.getTargetRotation() * IDENTITY_FRONT;
|
|
||||||
const float BASE_PUSHBACK_RADIUS = 0.25f;
|
|
||||||
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
|
|
||||||
glm::vec4 plane(planeNormal, -glm::dot(planeNormal, _myCamera.getTargetPosition()) - pushbackRadius);
|
|
||||||
|
|
||||||
// push camera out of any intersecting avatars
|
|
||||||
foreach (const AvatarSharedPointer& avatarData, _avatarManager.getAvatarHash()) {
|
|
||||||
Avatar* avatar = static_cast<Avatar*>(avatarData.data());
|
|
||||||
if (avatar->isMyAvatar()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (glm::distance(avatar->getPosition(), _myCamera.getTargetPosition()) >
|
|
||||||
avatar->getBoundingRadius() + pushbackRadius) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
float angle = angleBetween(avatar->getPosition() - _myCamera.getTargetPosition(), planeNormal);
|
|
||||||
if (angle > PI_OVER_TWO) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
float scale = 1.0f - angle / PI_OVER_TWO;
|
|
||||||
scale = qMin(1.0f, scale * 2.5f);
|
|
||||||
static CollisionList collisions(64);
|
|
||||||
collisions.clear();
|
|
||||||
if (!avatar->findPlaneCollisions(plane, collisions)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < collisions.size(); i++) {
|
|
||||||
pushback = qMax(pushback, glm::length(collisions.getCollision(i)->_penetration) * scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const float MAX_PUSHBACK = 0.35f;
|
|
||||||
pushback = qMin(pushback, MAX_PUSHBACK * _myAvatar->getScale());
|
|
||||||
const float BASE_PUSHBACK_FOCAL_LENGTH = 0.5f;
|
|
||||||
pushbackFocalLength = BASE_PUSHBACK_FOCAL_LENGTH * _myAvatar->getScale();
|
|
||||||
}
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
||||||
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
|
||||||
|
@ -3132,8 +3096,8 @@ void Application::updateWindowTitle(){
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
QString username = AccountManager::getInstance().getAccountInfo().getUsername();
|
QString username = AccountManager::getInstance().getAccountInfo().getUsername();
|
||||||
QString title = QString() + (!username.isEmpty() ? username + " " : QString()) + nodeList->getSessionUUID().toString()
|
QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())
|
||||||
+ " @ " + nodeList->getDomainHandler().getHostname() + buildVersion;
|
+ nodeList->getDomainHandler().getHostname() + buildVersion;
|
||||||
qDebug("Application title set to: %s", title.toStdString().c_str());
|
qDebug("Application title set to: %s", title.toStdString().c_str());
|
||||||
_window->setWindowTitle(title);
|
_window->setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QMoveEvent>
|
#include <QMoveEvent>
|
||||||
|
@ -56,6 +57,10 @@ void MainWindow::changeEvent(QEvent* event) {
|
||||||
} else {
|
} else {
|
||||||
emit windowShown(true);
|
emit windowShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
|
||||||
|
Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen());
|
||||||
|
}
|
||||||
} else if (event->type() == QEvent::ActivationChange) {
|
} else if (event->type() == QEvent::ActivationChange) {
|
||||||
if (isActiveWindow()) {
|
if (isActiveWindow()) {
|
||||||
emit windowShown(true);
|
emit windowShown(true);
|
||||||
|
|
|
@ -336,7 +336,6 @@ Menu::Menu() :
|
||||||
SLOT(setFilter(bool)));
|
SLOT(setFilter(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::PlaySlaps, 0, false);
|
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, true);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, true);
|
||||||
|
|
|
@ -340,7 +340,6 @@ namespace MenuOption {
|
||||||
const QString Particles = "Particles";
|
const QString Particles = "Particles";
|
||||||
const QString PasteToVoxel = "Paste to Voxel...";
|
const QString PasteToVoxel = "Paste to Voxel...";
|
||||||
const QString PipelineWarnings = "Show Render Pipeline Warnings";
|
const QString PipelineWarnings = "Show Render Pipeline Warnings";
|
||||||
const QString PlaySlaps = "Play Slaps";
|
|
||||||
const QString Preferences = "Preferences...";
|
const QString Preferences = "Preferences...";
|
||||||
const QString Quit = "Quit";
|
const QString Quit = "Quit";
|
||||||
const QString ReloadAllScripts = "Reload All Scripts";
|
const QString ReloadAllScripts = "Reload All Scripts";
|
||||||
|
|
|
@ -153,14 +153,14 @@ bool ModelUploader::zip() {
|
||||||
|
|
||||||
// mixamo/autodesk defaults
|
// mixamo/autodesk defaults
|
||||||
if (!mapping.contains(SCALE_FIELD)) {
|
if (!mapping.contains(SCALE_FIELD)) {
|
||||||
mapping.insert(SCALE_FIELD, 15.0);
|
mapping.insert(SCALE_FIELD, geometry.author == "www.makehuman.org" ? 150.0 : 15.0);
|
||||||
}
|
}
|
||||||
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
|
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
|
||||||
if (!joints.contains("jointEyeLeft")) {
|
if (!joints.contains("jointEyeLeft")) {
|
||||||
joints.insert("jointEyeLeft", "LeftEye");
|
joints.insert("jointEyeLeft", geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye");
|
||||||
}
|
}
|
||||||
if (!joints.contains("jointEyeRight")) {
|
if (!joints.contains("jointEyeRight")) {
|
||||||
joints.insert("jointEyeRight", "RightEye");
|
joints.insert("jointEyeRight", geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye");
|
||||||
}
|
}
|
||||||
if (!joints.contains("jointNeck")) {
|
if (!joints.contains("jointNeck")) {
|
||||||
joints.insert("jointNeck", "Neck");
|
joints.insert("jointNeck", "Neck");
|
||||||
|
@ -172,7 +172,8 @@ bool ModelUploader::zip() {
|
||||||
joints.insert("jointLean", "Spine");
|
joints.insert("jointLean", "Spine");
|
||||||
}
|
}
|
||||||
if (!joints.contains("jointHead")) {
|
if (!joints.contains("jointHead")) {
|
||||||
joints.insert("jointHead", geometry.applicationName == "mixamo.com" ? "HeadTop_End" : "HeadEnd");
|
const char* topName = (geometry.applicationName == "mixamo.com") ? "HeadTop_End" : "HeadEnd";
|
||||||
|
joints.insert("jointHead", geometry.jointIndices.contains(topName) ? topName : "Head");
|
||||||
}
|
}
|
||||||
if (!joints.contains("jointLeftHand")) {
|
if (!joints.contains("jointLeftHand")) {
|
||||||
joints.insert("jointLeftHand", "LeftHand");
|
joints.insert("jointLeftHand", "LeftHand");
|
||||||
|
|
|
@ -29,11 +29,11 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
neckPosition = owningAvatar->getPosition();
|
neckPosition = owningAvatar->getPosition();
|
||||||
}
|
}
|
||||||
setTranslation(neckPosition);
|
setTranslation(neckPosition);
|
||||||
glm::quat neckRotation;
|
glm::quat neckParentRotation;
|
||||||
if (!owningAvatar->getSkeletonModel().getNeckRotation(neckRotation)) {
|
if (!owningAvatar->getSkeletonModel().getNeckParentRotation(neckParentRotation)) {
|
||||||
neckRotation = owningAvatar->getOrientation();
|
neckParentRotation = owningAvatar->getOrientation();
|
||||||
}
|
}
|
||||||
setRotation(neckRotation);
|
setRotation(neckParentRotation);
|
||||||
const float MODEL_SCALE = 0.0006f;
|
const float MODEL_SCALE = 0.0006f;
|
||||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE);
|
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE);
|
||||||
|
|
||||||
|
|
|
@ -55,76 +55,10 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::playSlaps(PalmData& palm, Avatar* avatar) {
|
|
||||||
// Check for palm collisions
|
|
||||||
glm::vec3 myPalmPosition = palm.getPosition();
|
|
||||||
float palmCollisionDistance = 0.1f;
|
|
||||||
bool wasColliding = palm.getIsCollidingWithPalm();
|
|
||||||
palm.setIsCollidingWithPalm(false);
|
|
||||||
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
|
|
||||||
for (size_t j = 0; j < avatar->getHand()->getNumPalms(); j++) {
|
|
||||||
PalmData& otherPalm = avatar->getHand()->getPalms()[j];
|
|
||||||
if (!otherPalm.isActive()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
glm::vec3 otherPalmPosition = otherPalm.getPosition();
|
|
||||||
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
|
|
||||||
palm.setIsCollidingWithPalm(true);
|
|
||||||
if (!wasColliding) {
|
|
||||||
const float PALM_COLLIDE_VOLUME = 1.f;
|
|
||||||
const float PALM_COLLIDE_FREQUENCY = 1000.f;
|
|
||||||
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
|
|
||||||
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
|
|
||||||
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
|
|
||||||
PALM_COLLIDE_FREQUENCY,
|
|
||||||
PALM_COLLIDE_DURATION_MAX,
|
|
||||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
|
||||||
// If the other person's palm is in motion, move mine downward to show I was hit
|
|
||||||
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
|
|
||||||
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
|
|
||||||
// add slapback here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We create a static CollisionList that is recycled for each collision test.
|
// We create a static CollisionList that is recycled for each collision test.
|
||||||
const float MAX_COLLISIONS_PER_AVATAR = 32;
|
const float MAX_COLLISIONS_PER_AVATAR = 32;
|
||||||
static CollisionList handCollisions(MAX_COLLISIONS_PER_AVATAR);
|
static CollisionList handCollisions(MAX_COLLISIONS_PER_AVATAR);
|
||||||
|
|
||||||
void Hand::collideAgainstAvatarOld(Avatar* avatar, bool isMyHand) {
|
|
||||||
if (!avatar || avatar == _owningAvatar) {
|
|
||||||
// don't collide with our own hands (that is done elsewhere)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
|
|
||||||
for (size_t i = 0; i < getNumPalms(); i++) {
|
|
||||||
PalmData& palm = getPalms()[i];
|
|
||||||
if (!palm.isActive()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isMyHand && Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
|
|
||||||
playSlaps(palm, avatar);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 totalPenetration;
|
|
||||||
handCollisions.clear();
|
|
||||||
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, handCollisions)) {
|
|
||||||
for (int j = 0; j < handCollisions.size(); ++j) {
|
|
||||||
CollisionInfo* collision = handCollisions.getCollision(j);
|
|
||||||
if (isMyHand) {
|
|
||||||
totalPenetration = addPenetrations(totalPenetration, collision->_penetration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isMyHand) {
|
|
||||||
// resolve penetration
|
|
||||||
palm.addToPosition(-totalPenetration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
|
void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
|
||||||
if (!avatar || avatar == _owningAvatar) {
|
if (!avatar || avatar == _owningAvatar) {
|
||||||
// don't collide hands against ourself (that is done elsewhere)
|
// don't collide hands against ourself (that is done elsewhere)
|
||||||
|
|
|
@ -58,7 +58,6 @@ public:
|
||||||
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
|
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
|
||||||
const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;}
|
const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;}
|
||||||
|
|
||||||
void collideAgainstAvatarOld(Avatar* avatar, bool isMyHand);
|
|
||||||
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
|
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
|
||||||
void collideAgainstOurself();
|
void collideAgainstOurself();
|
||||||
|
|
||||||
|
@ -80,8 +79,6 @@ private:
|
||||||
void renderLeapFingerTrails();
|
void renderLeapFingerTrails();
|
||||||
|
|
||||||
void calculateGeometry();
|
void calculateGeometry();
|
||||||
|
|
||||||
void playSlaps(PalmData& palm, Avatar* avatar);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Hand_h
|
#endif // hifi_Hand_h
|
||||||
|
|
|
@ -434,6 +434,17 @@ bool Model::getNeckRotation(glm::quat& neckRotation) const {
|
||||||
return isActive() && getJointRotation(_geometry->getFBXGeometry().neckJointIndex, neckRotation);
|
return isActive() && getJointRotation(_geometry->getFBXGeometry().neckJointIndex, neckRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Model::getNeckParentRotation(glm::quat& neckParentRotation) const {
|
||||||
|
if (!isActive()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
if (geometry.neckJointIndex == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getJointRotation(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation);
|
||||||
|
}
|
||||||
|
|
||||||
bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -132,6 +132,10 @@ public:
|
||||||
/// \return whether or not the neck was found
|
/// \return whether or not the neck was found
|
||||||
bool getNeckRotation(glm::quat& neckRotation) const;
|
bool getNeckRotation(glm::quat& neckRotation) const;
|
||||||
|
|
||||||
|
/// Returns the rotation of the neck joint's parent.
|
||||||
|
/// \return whether or not the neck was found
|
||||||
|
bool getNeckParentRotation(glm::quat& neckRotation) const;
|
||||||
|
|
||||||
/// Retrieve the positions of up to two eye meshes.
|
/// Retrieve the positions of up to two eye meshes.
|
||||||
/// \return whether or not both eye meshes were found
|
/// \return whether or not both eye meshes were found
|
||||||
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
||||||
|
|
|
@ -19,7 +19,7 @@ ScriptLineNumberArea::ScriptLineNumberArea(ScriptEditBox* scriptEditBox) :
|
||||||
_scriptEditBox = scriptEditBox;
|
_scriptEditBox = scriptEditBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize ScriptLineNumberArea::sizeHint() {
|
QSize ScriptLineNumberArea::sizeHint() const {
|
||||||
return QSize(_scriptEditBox->lineNumberAreaWidth(), 0);
|
return QSize(_scriptEditBox->lineNumberAreaWidth(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ScriptLineNumberArea : public QWidget {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScriptLineNumberArea(ScriptEditBox* scriptEditBox);
|
ScriptLineNumberArea(ScriptEditBox* scriptEditBox);
|
||||||
QSize sizeHint();
|
QSize sizeHint() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent* event);
|
void paintEvent(QPaintEvent* event);
|
||||||
|
|
|
@ -406,7 +406,7 @@ QVariantHash parseMapping(QIODevice* device) {
|
||||||
|
|
||||||
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
||||||
QVector<glm::vec3> values;
|
QVector<glm::vec3> values;
|
||||||
for (const double* it = doubleVector.constData(), *end = it + doubleVector.size(); it != end; ) {
|
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 3 * 3); it != end; ) {
|
||||||
float x = *it++;
|
float x = *it++;
|
||||||
float y = *it++;
|
float y = *it++;
|
||||||
float z = *it++;
|
float z = *it++;
|
||||||
|
@ -417,7 +417,7 @@ QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
||||||
|
|
||||||
QVector<glm::vec2> createVec2Vector(const QVector<double>& doubleVector) {
|
QVector<glm::vec2> createVec2Vector(const QVector<double>& doubleVector) {
|
||||||
QVector<glm::vec2> values;
|
QVector<glm::vec2> values;
|
||||||
for (const double* it = doubleVector.constData(), *end = it + doubleVector.size(); it != end; ) {
|
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 2 * 2); it != end; ) {
|
||||||
float s = *it++;
|
float s = *it++;
|
||||||
float t = *it++;
|
float t = *it++;
|
||||||
values.append(glm::vec2(s, -t));
|
values.append(glm::vec2(s, -t));
|
||||||
|
@ -432,58 +432,59 @@ glm::mat4 createMat4(const QVector<double>& doubleVector) {
|
||||||
doubleVector.at(12), doubleVector.at(13), doubleVector.at(14), doubleVector.at(15));
|
doubleVector.at(12), doubleVector.at(13), doubleVector.at(14), doubleVector.at(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<int> getIntVector(const QVariantList& properties, int index) {
|
QVector<int> getIntVector(const FBXNode& node) {
|
||||||
if (index >= properties.size()) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
|
if (child.name == "a") {
|
||||||
|
return getIntVector(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.properties.isEmpty()) {
|
||||||
return QVector<int>();
|
return QVector<int>();
|
||||||
}
|
}
|
||||||
QVector<int> vector = properties.at(index).value<QVector<int> >();
|
QVector<int> vector = node.properties.at(0).value<QVector<int> >();
|
||||||
if (!vector.isEmpty()) {
|
if (!vector.isEmpty()) {
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
for (; index < properties.size(); index++) {
|
for (int i = 0; i < node.properties.size(); i++) {
|
||||||
vector.append(properties.at(index).toInt());
|
vector.append(node.properties.at(i).toInt());
|
||||||
}
|
}
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<qlonglong> getLongVector(const QVariantList& properties, int index) {
|
QVector<float> getFloatVector(const FBXNode& node) {
|
||||||
if (index >= properties.size()) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
return QVector<qlonglong>();
|
if (child.name == "a") {
|
||||||
|
return getFloatVector(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
QVector<qlonglong> vector = properties.at(index).value<QVector<qlonglong> >();
|
if (node.properties.isEmpty()) {
|
||||||
if (!vector.isEmpty()) {
|
|
||||||
return vector;
|
|
||||||
}
|
|
||||||
for (; index < properties.size(); index++) {
|
|
||||||
vector.append(properties.at(index).toLongLong());
|
|
||||||
}
|
|
||||||
return vector;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<float> getFloatVector(const QVariantList& properties, int index) {
|
|
||||||
if (index >= properties.size()) {
|
|
||||||
return QVector<float>();
|
return QVector<float>();
|
||||||
}
|
}
|
||||||
QVector<float> vector = properties.at(index).value<QVector<float> >();
|
QVector<float> vector = node.properties.at(0).value<QVector<float> >();
|
||||||
if (!vector.isEmpty()) {
|
if (!vector.isEmpty()) {
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
for (; index < properties.size(); index++) {
|
for (int i = 0; i < node.properties.size(); i++) {
|
||||||
vector.append(properties.at(index).toFloat());
|
vector.append(node.properties.at(i).toFloat());
|
||||||
}
|
}
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<double> getDoubleVector(const QVariantList& properties, int index) {
|
QVector<double> getDoubleVector(const FBXNode& node) {
|
||||||
if (index >= properties.size()) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
|
if (child.name == "a") {
|
||||||
|
return getDoubleVector(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.properties.isEmpty()) {
|
||||||
return QVector<double>();
|
return QVector<double>();
|
||||||
}
|
}
|
||||||
QVector<double> vector = properties.at(index).value<QVector<double> >();
|
QVector<double> vector = node.properties.at(0).value<QVector<double> >();
|
||||||
if (!vector.isEmpty()) {
|
if (!vector.isEmpty()) {
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
for (; index < properties.size(); index++) {
|
for (int i = 0; i < node.properties.size(); i++) {
|
||||||
vector.append(properties.at(index).toDouble());
|
vector.append(node.properties.at(i).toDouble());
|
||||||
}
|
}
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
@ -697,21 +698,30 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
|
if (index >= data.polygonIndices.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int vertexIndex = data.polygonIndices.at(index);
|
int vertexIndex = data.polygonIndices.at(index);
|
||||||
if (vertexIndex < 0) {
|
if (vertexIndex < 0) {
|
||||||
vertexIndex = -vertexIndex - 1;
|
vertexIndex = -vertexIndex - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex vertex;
|
Vertex vertex;
|
||||||
vertex.originalIndex = vertexIndex;
|
vertex.originalIndex = vertexIndex;
|
||||||
|
|
||||||
|
glm::vec3 position;
|
||||||
|
if (vertexIndex < data.vertices.size()) {
|
||||||
|
position = data.vertices.at(vertexIndex);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 normal;
|
glm::vec3 normal;
|
||||||
if (data.normalIndices.isEmpty()) {
|
int normalIndex = data.normalsByVertex ? vertexIndex : index;
|
||||||
normal = data.normals.at(data.normalsByVertex ? vertexIndex : index);
|
if (data.normalIndices.isEmpty()) {
|
||||||
|
if (normalIndex < data.normals.size()) {
|
||||||
} else {
|
normal = data.normals.at(normalIndex);
|
||||||
int normalIndex = data.normalIndices.at(data.normalsByVertex ? vertexIndex : index);
|
}
|
||||||
if (normalIndex >= 0) {
|
} else if (normalIndex < data.normalIndices.size()) {
|
||||||
|
normalIndex = data.normalIndices.at(normalIndex);
|
||||||
|
if (normalIndex >= 0 && normalIndex < data.normals.size()) {
|
||||||
normal = data.normals.at(normalIndex);
|
normal = data.normals.at(normalIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -720,9 +730,9 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
if (index < data.texCoords.size()) {
|
if (index < data.texCoords.size()) {
|
||||||
vertex.texCoord = data.texCoords.at(index);
|
vertex.texCoord = data.texCoords.at(index);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (index < data.texCoordIndices.size()) {
|
||||||
int texCoordIndex = data.texCoordIndices.at(index);
|
int texCoordIndex = data.texCoordIndices.at(index);
|
||||||
if (texCoordIndex >= 0) {
|
if (texCoordIndex >= 0 && texCoordIndex < data.texCoords.size()) {
|
||||||
vertex.texCoord = data.texCoords.at(texCoordIndex);
|
vertex.texCoord = data.texCoords.at(texCoordIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,7 +743,7 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
indices.append(newIndex);
|
indices.append(newIndex);
|
||||||
data.indices.insert(vertex, newIndex);
|
data.indices.insert(vertex, newIndex);
|
||||||
data.extracted.newIndices.insert(vertexIndex, newIndex);
|
data.extracted.newIndices.insert(vertexIndex, newIndex);
|
||||||
data.extracted.mesh.vertices.append(data.vertices.at(vertexIndex));
|
data.extracted.mesh.vertices.append(position);
|
||||||
data.extracted.mesh.normals.append(normal);
|
data.extracted.mesh.normals.append(normal);
|
||||||
data.extracted.mesh.texCoords.append(vertex.texCoord);
|
data.extracted.mesh.texCoords.append(vertex.texCoord);
|
||||||
|
|
||||||
|
@ -749,44 +759,51 @@ ExtractedMesh extractMesh(const FBXNode& object) {
|
||||||
QVector<int> textures;
|
QVector<int> textures;
|
||||||
foreach (const FBXNode& child, object.children) {
|
foreach (const FBXNode& child, object.children) {
|
||||||
if (child.name == "Vertices") {
|
if (child.name == "Vertices") {
|
||||||
data.vertices = createVec3Vector(getDoubleVector(child.properties, 0));
|
data.vertices = createVec3Vector(getDoubleVector(child));
|
||||||
|
|
||||||
} else if (child.name == "PolygonVertexIndex") {
|
} else if (child.name == "PolygonVertexIndex") {
|
||||||
data.polygonIndices = getIntVector(child.properties, 0);
|
data.polygonIndices = getIntVector(child);
|
||||||
|
|
||||||
} else if (child.name == "LayerElementNormal") {
|
} else if (child.name == "LayerElementNormal") {
|
||||||
data.normalsByVertex = false;
|
data.normalsByVertex = false;
|
||||||
|
bool indexToDirect = false;
|
||||||
foreach (const FBXNode& subdata, child.children) {
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
if (subdata.name == "Normals") {
|
if (subdata.name == "Normals") {
|
||||||
data.normals = createVec3Vector(getDoubleVector(subdata.properties, 0));
|
data.normals = createVec3Vector(getDoubleVector(subdata));
|
||||||
|
|
||||||
} else if (subdata.name == "NormalsIndex") {
|
} else if (subdata.name == "NormalsIndex") {
|
||||||
data.normalIndices = getIntVector(subdata.properties, 0);
|
data.normalIndices = getIntVector(subdata);
|
||||||
|
|
||||||
} else if (subdata.name == "MappingInformationType" &&
|
} else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == "ByVertice") {
|
||||||
subdata.properties.at(0) == "ByVertice") {
|
|
||||||
data.normalsByVertex = true;
|
data.normalsByVertex = true;
|
||||||
|
|
||||||
|
} else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == "IndexToDirect") {
|
||||||
|
indexToDirect = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (indexToDirect && data.normalIndices.isEmpty()) {
|
||||||
|
// hack to work around wacky Makehuman exports
|
||||||
|
data.normalsByVertex = true;
|
||||||
|
}
|
||||||
} else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) {
|
} else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) {
|
||||||
foreach (const FBXNode& subdata, child.children) {
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
if (subdata.name == "UV") {
|
if (subdata.name == "UV") {
|
||||||
data.texCoords = createVec2Vector(getDoubleVector(subdata.properties, 0));
|
data.texCoords = createVec2Vector(getDoubleVector(subdata));
|
||||||
|
|
||||||
} else if (subdata.name == "UVIndex") {
|
} else if (subdata.name == "UVIndex") {
|
||||||
data.texCoordIndices = getIntVector(subdata.properties, 0);
|
data.texCoordIndices = getIntVector(subdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.name == "LayerElementMaterial") {
|
} else if (child.name == "LayerElementMaterial") {
|
||||||
foreach (const FBXNode& subdata, child.children) {
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
if (subdata.name == "Materials") {
|
if (subdata.name == "Materials") {
|
||||||
materials = getIntVector(subdata.properties, 0);
|
materials = getIntVector(subdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.name == "LayerElementTexture") {
|
} else if (child.name == "LayerElementTexture") {
|
||||||
foreach (const FBXNode& subdata, child.children) {
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
if (subdata.name == "TextureId") {
|
if (subdata.name == "TextureId") {
|
||||||
textures = getIntVector(subdata.properties, 0);
|
textures = getIntVector(subdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,7 +814,7 @@ ExtractedMesh extractMesh(const FBXNode& object) {
|
||||||
QHash<QPair<int, int>, int> materialTextureParts;
|
QHash<QPair<int, int>, int> materialTextureParts;
|
||||||
for (int beginIndex = 0; beginIndex < data.polygonIndices.size(); polygonIndex++) {
|
for (int beginIndex = 0; beginIndex < data.polygonIndices.size(); polygonIndex++) {
|
||||||
int endIndex = beginIndex;
|
int endIndex = beginIndex;
|
||||||
while (data.polygonIndices.at(endIndex++) >= 0);
|
while (endIndex < data.polygonIndices.size() && data.polygonIndices.at(endIndex++) >= 0);
|
||||||
|
|
||||||
QPair<int, int> materialTexture((polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0,
|
QPair<int, int> materialTexture((polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0,
|
||||||
(polygonIndex < textures.size()) ? textures.at(polygonIndex) : 0);
|
(polygonIndex < textures.size()) ? textures.at(polygonIndex) : 0);
|
||||||
|
@ -820,7 +837,7 @@ ExtractedMesh extractMesh(const FBXNode& object) {
|
||||||
appendIndex(data, part.triangleIndices, beginIndex);
|
appendIndex(data, part.triangleIndices, beginIndex);
|
||||||
appendIndex(data, part.triangleIndices, nextIndex++);
|
appendIndex(data, part.triangleIndices, nextIndex++);
|
||||||
appendIndex(data, part.triangleIndices, nextIndex);
|
appendIndex(data, part.triangleIndices, nextIndex);
|
||||||
if (data.polygonIndices.at(nextIndex) < 0) {
|
if (nextIndex >= data.polygonIndices.size() || data.polygonIndices.at(nextIndex) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,13 +852,13 @@ FBXBlendshape extractBlendshape(const FBXNode& object) {
|
||||||
FBXBlendshape blendshape;
|
FBXBlendshape blendshape;
|
||||||
foreach (const FBXNode& data, object.children) {
|
foreach (const FBXNode& data, object.children) {
|
||||||
if (data.name == "Indexes") {
|
if (data.name == "Indexes") {
|
||||||
blendshape.indices = getIntVector(data.properties, 0);
|
blendshape.indices = getIntVector(data);
|
||||||
|
|
||||||
} else if (data.name == "Vertices") {
|
} else if (data.name == "Vertices") {
|
||||||
blendshape.vertices = createVec3Vector(getDoubleVector(data.properties, 0));
|
blendshape.vertices = createVec3Vector(getDoubleVector(data));
|
||||||
|
|
||||||
} else if (data.name == "Normals") {
|
} else if (data.name == "Normals") {
|
||||||
blendshape.normals = createVec3Vector(getDoubleVector(data.properties, 0));
|
blendshape.normals = createVec3Vector(getDoubleVector(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return blendshape;
|
return blendshape;
|
||||||
|
@ -1016,7 +1033,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
foreach (const FBXNode& object, child.children) {
|
foreach (const FBXNode& object, child.children) {
|
||||||
if (object.name == "SceneInfo") {
|
if (object.name == "SceneInfo") {
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "Properties70") {
|
if (subobject.name == "MetaData") {
|
||||||
|
foreach (const FBXNode& subsubobject, subobject.children) {
|
||||||
|
if (subsubobject.name == "Author") {
|
||||||
|
geometry.author = subsubobject.properties.at(0).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (subobject.name == "Properties70") {
|
||||||
foreach (const FBXNode& subsubobject, subobject.children) {
|
foreach (const FBXNode& subsubobject, subobject.children) {
|
||||||
if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 &&
|
if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 &&
|
||||||
subsubobject.properties.at(0) == "Original|ApplicationName") {
|
subsubobject.properties.at(0) == "Original|ApplicationName") {
|
||||||
|
@ -1262,13 +1285,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
Cluster cluster;
|
Cluster cluster;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "Indexes") {
|
if (subobject.name == "Indexes") {
|
||||||
cluster.indices = getIntVector(subobject.properties, 0);
|
cluster.indices = getIntVector(subobject);
|
||||||
|
|
||||||
} else if (subobject.name == "Weights") {
|
} else if (subobject.name == "Weights") {
|
||||||
cluster.weights = getDoubleVector(subobject.properties, 0);
|
cluster.weights = getDoubleVector(subobject);
|
||||||
|
|
||||||
} else if (subobject.name == "TransformLink") {
|
} else if (subobject.name == "TransformLink") {
|
||||||
QVector<double> values = getDoubleVector(subobject.properties, 0);
|
QVector<double> values = getDoubleVector(subobject);
|
||||||
cluster.transformLink = createMat4(values);
|
cluster.transformLink = createMat4(values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1313,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
AnimationCurve curve;
|
AnimationCurve curve;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "KeyValueFloat") {
|
if (subobject.name == "KeyValueFloat") {
|
||||||
curve.values = getFloatVector(subobject.properties, 0);
|
curve.values = getFloatVector(subobject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
animationCurves.insert(getID(object.properties), curve);
|
animationCurves.insert(getID(object.properties), curve);
|
||||||
|
|
|
@ -177,6 +177,7 @@ public:
|
||||||
class FBXGeometry {
|
class FBXGeometry {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
QString author;
|
||||||
QString applicationName; ///< the name of the application that generated the model
|
QString applicationName; ///< the name of the application that generated the model
|
||||||
|
|
||||||
QVector<FBXJoint> joints;
|
QVector<FBXJoint> joints;
|
||||||
|
|
Loading…
Reference in a new issue