mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-06 12:22:08 +02:00
Merge pull request #2952 from Atlante45/click_drag_attach
Click drag attach!
This commit is contained in:
commit
f42199b3e1
6 changed files with 136 additions and 19 deletions
|
@ -40,6 +40,8 @@ var modelURLs = [
|
||||||
|
|
||||||
var toolBar;
|
var toolBar;
|
||||||
|
|
||||||
|
var jointList = MyAvatar.getJointNames();
|
||||||
|
|
||||||
function isLocked(properties) {
|
function isLocked(properties) {
|
||||||
// special case to lock the ground plane model in hq.
|
// special case to lock the ground plane model in hq.
|
||||||
if (location.hostname == "hq.highfidelity.io" &&
|
if (location.hostname == "hq.highfidelity.io" &&
|
||||||
|
@ -81,10 +83,13 @@ function controller(wichSide) {
|
||||||
|
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.modelID = { isKnownID: false };
|
this.modelID = { isKnownID: false };
|
||||||
|
this.modelURL = "";
|
||||||
this.oldModelRotation;
|
this.oldModelRotation;
|
||||||
this.oldModelPosition;
|
this.oldModelPosition;
|
||||||
this.oldModelRadius;
|
this.oldModelRadius;
|
||||||
|
|
||||||
|
this.jointsIntersectingFromStart = [];
|
||||||
|
|
||||||
this.laser = Overlays.addOverlay("line3d", {
|
this.laser = Overlays.addOverlay("line3d", {
|
||||||
position: { x: 0, y: 0, z: 0 },
|
position: { x: 0, y: 0, z: 0 },
|
||||||
end: { x: 0, y: 0, z: 0 },
|
end: { x: 0, y: 0, z: 0 },
|
||||||
|
@ -134,16 +139,65 @@ function controller(wichSide) {
|
||||||
|
|
||||||
this.grabbing = true;
|
this.grabbing = true;
|
||||||
this.modelID = modelID;
|
this.modelID = modelID;
|
||||||
|
this.modelURL = properties.modelURL;
|
||||||
|
|
||||||
this.oldModelPosition = properties.position;
|
this.oldModelPosition = properties.position;
|
||||||
this.oldModelRotation = properties.modelRotation;
|
this.oldModelRotation = properties.modelRotation;
|
||||||
this.oldModelRadius = properties.radius;
|
this.oldModelRadius = properties.radius;
|
||||||
|
|
||||||
|
this.jointsIntersectingFromStart = [];
|
||||||
|
for (var i = 0; i < jointList.length; i++) {
|
||||||
|
var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition);
|
||||||
|
if (distance < this.oldModelRadius) {
|
||||||
|
this.jointsIntersectingFromStart.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.release = function () {
|
this.release = function () {
|
||||||
|
if (this.grabbing) {
|
||||||
|
if (jointList.length <= 0) {
|
||||||
|
jointList = MyAvatar.getJointNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
var closestJointIndex = -1;
|
||||||
|
var closestJointDistance = 10;
|
||||||
|
for (var i = 0; i < jointList.length; i++) {
|
||||||
|
var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition);
|
||||||
|
if (distance < closestJointDistance) {
|
||||||
|
closestJointDistance = distance;
|
||||||
|
closestJointIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("closestJoint: " + jointList[closestJointIndex]);
|
||||||
|
print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelRadius + ")");
|
||||||
|
|
||||||
|
if (closestJointDistance < this.oldModelRadius) {
|
||||||
|
|
||||||
|
if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1) {
|
||||||
|
// Do nothing
|
||||||
|
} else {
|
||||||
|
print("Attaching to " + jointList[closestJointIndex]);
|
||||||
|
var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]);
|
||||||
|
var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]);
|
||||||
|
|
||||||
|
var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition);
|
||||||
|
attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset);
|
||||||
|
var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation);
|
||||||
|
|
||||||
|
MyAvatar.attach(this.modelURL, jointList[closestJointIndex],
|
||||||
|
attachmentOffset, attachmentRotation, 2.0 * this.oldModelRadius,
|
||||||
|
true, false);
|
||||||
|
Models.deleteModel(this.modelID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.modelID.isKnownID = false;
|
this.modelID.isKnownID = false;
|
||||||
|
this.jointsIntersectingFromStart = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkTrigger = function () {
|
this.checkTrigger = function () {
|
||||||
|
@ -251,11 +305,6 @@ function controller(wichSide) {
|
||||||
position: newPosition,
|
position: newPosition,
|
||||||
modelRotation: newRotation
|
modelRotation: newRotation
|
||||||
});
|
});
|
||||||
// print("Moving " + this.modelID.id);
|
|
||||||
// Vec3.print("Old Position: ", this.oldModelPosition);
|
|
||||||
// Vec3.print("Sav Position: ", newPosition);
|
|
||||||
// Quat.print("Old Rotation: ", this.oldModelRotation);
|
|
||||||
// Quat.print("New Rotation: ", newRotation);
|
|
||||||
|
|
||||||
this.oldModelRotation = newRotation;
|
this.oldModelRotation = newRotation;
|
||||||
this.oldModelPosition = newPosition;
|
this.oldModelPosition = newPosition;
|
||||||
|
@ -410,8 +459,6 @@ function checkController(deltaTime) {
|
||||||
moveOverlays();
|
moveOverlays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function initToolBar() {
|
function initToolBar() {
|
||||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL);
|
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL);
|
||||||
// New Model
|
// New Model
|
||||||
|
|
|
@ -28,8 +28,10 @@ var NEW_VOXEL_SIZE = 1.0;
|
||||||
var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0;
|
var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0;
|
||||||
var PIXELS_PER_EXTRUDE_VOXEL = 16;
|
var PIXELS_PER_EXTRUDE_VOXEL = 16;
|
||||||
var WHEEL_PIXELS_PER_SCALE_CHANGE = 100;
|
var WHEEL_PIXELS_PER_SCALE_CHANGE = 100;
|
||||||
var MAX_VOXEL_SCALE = 16.0;
|
var MAX_VOXEL_SCALE_POWER = 4;
|
||||||
var MIN_VOXEL_SCALE = 1.0 / Math.pow(2.0, 8.0);
|
var MIN_VOXEL_SCALE_POWER = -8;
|
||||||
|
var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER);
|
||||||
|
var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER);
|
||||||
var WHITE_COLOR = { red: 255, green: 255, blue: 255 };
|
var WHITE_COLOR = { red: 255, green: 255, blue: 255 };
|
||||||
|
|
||||||
var MAX_PASTE_VOXEL_SCALE = 256;
|
var MAX_PASTE_VOXEL_SCALE = 256;
|
||||||
|
@ -330,6 +332,13 @@ function ScaleSelector() {
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
this.setScale = function(scale) {
|
this.setScale = function(scale) {
|
||||||
|
if (scale > MAX_VOXEL_SCALE) {
|
||||||
|
scale = MAX_VOXEL_SCALE;
|
||||||
|
}
|
||||||
|
if (scale < MIN_VOXEL_SCALE) {
|
||||||
|
scale = MIN_VOXEL_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.power = Math.floor(Math.log(scale) / Math.log(2));
|
this.power = Math.floor(Math.log(scale) / Math.log(2));
|
||||||
rescaleImport();
|
rescaleImport();
|
||||||
|
@ -391,12 +400,9 @@ function ScaleSelector() {
|
||||||
|
|
||||||
this.incrementScale = function() {
|
this.incrementScale = function() {
|
||||||
copyScale = false;
|
copyScale = false;
|
||||||
if (this.power < 13) {
|
if (this.power < MAX_VOXEL_SCALE_POWER) {
|
||||||
++this.power;
|
++this.power;
|
||||||
this.scale *= 2.0;
|
this.scale *= 2.0;
|
||||||
if (this.scale > MAX_VOXEL_SCALE) {
|
|
||||||
this.scale = MAX_VOXEL_SCALE;
|
|
||||||
}
|
|
||||||
this.update();
|
this.update();
|
||||||
rescaleImport();
|
rescaleImport();
|
||||||
resizeVoxelSound.play(voxelSizePlus);
|
resizeVoxelSound.play(voxelSizePlus);
|
||||||
|
@ -405,7 +411,7 @@ function ScaleSelector() {
|
||||||
|
|
||||||
this.decrementScale = function() {
|
this.decrementScale = function() {
|
||||||
copyScale = false;
|
copyScale = false;
|
||||||
if (-4 < this.power) {
|
if (MIN_VOXEL_SCALE_POWER < this.power) {
|
||||||
--this.power;
|
--this.power;
|
||||||
this.scale /= 2.0;
|
this.scale /= 2.0;
|
||||||
this.update();
|
this.update();
|
||||||
|
|
|
@ -378,10 +378,10 @@ void Avatar::simulateAttachments(float deltaTime) {
|
||||||
model->setLODDistance(getLODDistance());
|
model->setLODDistance(getLODDistance());
|
||||||
}
|
}
|
||||||
if (_skeletonModel.getJointPosition(jointIndex, jointPosition) &&
|
if (_skeletonModel.getJointPosition(jointIndex, jointPosition) &&
|
||||||
_skeletonModel.getJointRotation(jointIndex, jointRotation)) {
|
_skeletonModel.getJointCombinedRotation(jointIndex, jointRotation)) {
|
||||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale);
|
model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale);
|
||||||
model->setRotation(jointRotation * attachment.rotation);
|
model->setRotation(jointRotation * attachment.rotation);
|
||||||
model->setScale(_skeletonModel.getScale() * attachment.scale);
|
model->setScaleToFit(true, _scale * attachment.scale);
|
||||||
model->simulate(deltaTime);
|
model->simulate(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -705,6 +705,54 @@ QStringList Avatar::getJointNames() const {
|
||||||
return _skeletonModel.isActive() ? _skeletonModel.getGeometry()->getFBXGeometry().getJointNames() : QStringList();
|
return _skeletonModel.isActive() ? _skeletonModel.getGeometry()->getFBXGeometry().getJointNames() : QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Avatar::getJointPosition(int index) const {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
glm::vec3 position;
|
||||||
|
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointPosition", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index));
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
glm::vec3 position;
|
||||||
|
_skeletonModel.getJointPosition(index, position);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
glm::vec3 position;
|
||||||
|
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointPosition", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name));
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
glm::vec3 position;
|
||||||
|
_skeletonModel.getJointPosition(getJointIndex(name), position);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Avatar::getJointCombinedRotation(int index) const {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
glm::quat rotation;
|
||||||
|
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointCombinedRotation", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(glm::quat, rotation), Q_ARG(const int, index));
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
glm::quat rotation;
|
||||||
|
_skeletonModel.getJointCombinedRotation(index, rotation);
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Avatar::getJointCombinedRotation(const QString& name) const {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
glm::quat rotation;
|
||||||
|
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointCombinedRotation", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(glm::quat, rotation), Q_ARG(const QString&, name));
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
glm::quat rotation;
|
||||||
|
_skeletonModel.getJointCombinedRotation(getJointIndex(name), rotation);
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||||
AvatarData::setFaceModelURL(faceModelURL);
|
AvatarData::setFaceModelURL(faceModelURL);
|
||||||
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_head.fst");
|
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_head.fst");
|
||||||
|
@ -734,6 +782,8 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
|
|
||||||
// update the urls
|
// update the urls
|
||||||
for (int i = 0; i < attachmentData.size(); i++) {
|
for (int i = 0; i < attachmentData.size(); i++) {
|
||||||
|
_attachmentModels[i]->setSnapModelToCenter(true);
|
||||||
|
_attachmentModels[i]->setScaleToFit(true, _scale * _attachmentData.at(i).scale);
|
||||||
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,12 @@ public:
|
||||||
|
|
||||||
quint32 getCollisionGroups() const { return _collisionGroups; }
|
quint32 getCollisionGroups() const { return _collisionGroups; }
|
||||||
virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); }
|
virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); }
|
||||||
|
|
||||||
|
Q_INVOKABLE glm::vec3 getJointPosition(int index) const;
|
||||||
|
Q_INVOKABLE glm::vec3 getJointPosition(const QString& name) const;
|
||||||
|
Q_INVOKABLE glm::quat getJointCombinedRotation(int index) const;
|
||||||
|
Q_INVOKABLE glm::quat getJointCombinedRotation(const QString& name) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateCollisionGroups();
|
void updateCollisionGroups();
|
||||||
|
|
||||||
|
|
|
@ -634,8 +634,16 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rotation = _jointStates[jointIndex]._combinedRotation *
|
rotation = _jointStates[jointIndex]._combinedRotation *
|
||||||
(fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation :
|
(fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation :
|
||||||
_geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation);
|
_geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const {
|
||||||
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rotation = _jointStates[jointIndex]._combinedRotation;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,7 @@ public:
|
||||||
|
|
||||||
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
||||||
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
|
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
|
||||||
|
bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const;
|
||||||
|
|
||||||
QStringList getJointNames() const;
|
QStringList getJointNames() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue