mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 12:23:24 +02:00
Minimum chat circle radius from Ryan, basic avatar/voxel orbit behavior.
This commit is contained in:
parent
1003393101
commit
aa9fc290a5
10 changed files with 135 additions and 12 deletions
|
@ -1105,9 +1105,24 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
}
|
||||
|
||||
if (activeWindow() == _window) {
|
||||
int deltaX = event->x() - _mouseX;
|
||||
int deltaY = event->y() - _mouseY;
|
||||
|
||||
_mouseX = event->x();
|
||||
_mouseY = event->y();
|
||||
|
||||
// orbit behavior
|
||||
if (_mousePressed && !Menu::getInstance()->isVoxelModeActionChecked()) {
|
||||
if (_lookatTargetAvatar) {
|
||||
_myAvatar.orbit(_lookatTargetAvatar->getPosition(), deltaX, deltaY);
|
||||
return;
|
||||
}
|
||||
if (_isHoverVoxel) {
|
||||
_myAvatar.orbit(glm::vec3(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z) * (float)TREE_SCALE, deltaX, deltaY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// detect drag
|
||||
glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
||||
if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) {
|
||||
|
@ -1151,7 +1166,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
}
|
||||
|
||||
if (!_palette.isActive() && (!_isHoverVoxel || _lookatTargetAvatar)) {
|
||||
_pieMenu.mousePressEvent(_mouseX, _mouseY);
|
||||
// disable for now
|
||||
// _pieMenu.mousePressEvent(_mouseX, _mouseY);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode) && _pasteMode) {
|
||||
|
@ -1952,7 +1968,9 @@ void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, cons
|
|||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateLookatTargetAvatar()");
|
||||
|
||||
_lookatTargetAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, DEFAULT_NODE_ID_REF);
|
||||
if (!_mousePressed) {
|
||||
_lookatTargetAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, DEFAULT_NODE_ID_REF);
|
||||
}
|
||||
}
|
||||
|
||||
Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection,
|
||||
|
@ -1961,17 +1979,15 @@ Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, con
|
|||
NodeList* nodeList = NodeList::getInstance();
|
||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
|
||||
Avatar* avatar = (Avatar *) node->getLinkedData();
|
||||
glm::vec3 headPosition = avatar->getHead().getPosition();
|
||||
Avatar* avatar = (Avatar*)node->getLinkedData();
|
||||
float distance;
|
||||
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition,
|
||||
HEAD_SPHERE_RADIUS * avatar->getHead().getScale(), distance)) {
|
||||
if (avatar->findRayIntersection(mouseRayOrigin, mouseRayDirection, distance)) {
|
||||
// rescale to compensate for head embiggening
|
||||
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
|
||||
|
||||
_lookatIndicatorScale = avatar->getHead().getScale();
|
||||
_lookatOtherPosition = headPosition;
|
||||
_lookatOtherPosition = avatar->getHead().getPosition();
|
||||
nodeUUID = avatar->getOwningNode()->getUUID();
|
||||
return avatar;
|
||||
}
|
||||
|
@ -2213,7 +2229,7 @@ void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin,
|
|||
glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
||||
// only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled,
|
||||
// and make sure the tree is not already busy... because otherwise you'll have to wait.
|
||||
if (!_voxels.treeIsBusy()) {
|
||||
if (!(_voxels.treeIsBusy() || _mousePressed)) {
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||
_isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face);
|
||||
|
|
|
@ -336,8 +336,24 @@ void Avatar::getSkinColors(glm::vec3& lighter, glm::vec3& darker) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
float minDistance = FLT_MAX;
|
||||
float modelDistance;
|
||||
if (_skeletonModel.findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (_head.getFaceModel().findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
distance = minDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||
glm::vec3& penetration, int skeletonSkipIndex) {
|
||||
glm::vec3& penetration, int skeletonSkipIndex) const {
|
||||
bool didPenetrate = false;
|
||||
glm::vec3 totalPenetration;
|
||||
glm::vec3 skeletonPenetration;
|
||||
|
|
|
@ -160,6 +160,8 @@ public:
|
|||
|
||||
void getSkinColors(glm::vec3& lighter, glm::vec3& darker);
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
/// Checks for penetration between the described sphere and the avatar.
|
||||
/// \param penetratorCenter the center of the penetration test sphere
|
||||
/// \param penetratorRadius the radius of the penetration test sphere
|
||||
|
@ -167,7 +169,7 @@ public:
|
|||
/// \param skeletonSkipIndex if not -1, the index of a joint to skip (along with its descendents) in the skeleton model
|
||||
/// \return whether or not the sphere penetrated
|
||||
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||
glm::vec3& penetration, int skeletonSkipIndex = -1);
|
||||
glm::vec3& penetration, int skeletonSkipIndex = -1) const;
|
||||
|
||||
virtual int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
VideoFace& getVideoFace() { return _videoFace; }
|
||||
FaceModel& getFaceModel() { return _faceModel; }
|
||||
const FaceModel& getFaceModel() const { return _faceModel; }
|
||||
|
||||
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
||||
float getAverageLoudness() const { return _averageLoudness; }
|
||||
|
|
|
@ -542,6 +542,16 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
settings->endGroup();
|
||||
}
|
||||
|
||||
void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
|
||||
glm::vec3 vector = getPosition() - position;
|
||||
glm::quat orientation = getOrientation();
|
||||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
const float ANGULAR_SCALE = 0.5f;
|
||||
glm::quat rotation = glm::angleAxis(deltaX * -ANGULAR_SCALE, up);
|
||||
const float LINEAR_SCALE = 0.01f;
|
||||
setPosition(position + rotation * vector + up * (deltaY * LINEAR_SCALE * _scale));
|
||||
setOrientation(rotation * orientation);
|
||||
}
|
||||
|
||||
float MyAvatar::getAbsoluteHeadYaw() const {
|
||||
return glm::yaw(_head.getOrientation());
|
||||
|
@ -909,8 +919,9 @@ void MyAvatar::updateChatCircle(float deltaTime) {
|
|||
// remove members whose accumulated circles are too far away to influence us
|
||||
const float CIRCUMFERENCE_PER_MEMBER = 0.5f;
|
||||
const float CIRCLE_INFLUENCE_SCALE = 2.0f;
|
||||
const float MIN_RADIUS = 0.3f;
|
||||
for (int i = sortedAvatars.size() - 1; i >= 0; i--) {
|
||||
float radius = (CIRCUMFERENCE_PER_MEMBER * (i + 2)) / PI_TIMES_TWO;
|
||||
float radius = qMax(MIN_RADIUS, (CIRCUMFERENCE_PER_MEMBER * (i + 2)) / PI_TIMES_TWO);
|
||||
if (glm::distance(_position, sortedAvatars[i].accumulatedCenter) > radius * CIRCLE_INFLUENCE_SCALE) {
|
||||
sortedAvatars.remove(i);
|
||||
} else {
|
||||
|
@ -921,7 +932,7 @@ void MyAvatar::updateChatCircle(float deltaTime) {
|
|||
return;
|
||||
}
|
||||
center = sortedAvatars.last().accumulatedCenter;
|
||||
float radius = (CIRCUMFERENCE_PER_MEMBER * (sortedAvatars.size() + 1)) / PI_TIMES_TWO;
|
||||
float radius = qMax(MIN_RADIUS, (CIRCUMFERENCE_PER_MEMBER * (sortedAvatars.size() + 1)) / PI_TIMES_TWO);
|
||||
|
||||
// compute the average up vector
|
||||
glm::vec3 up = getWorldAlignedOrientation() * IDENTITY_UP;
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
void orbit(const glm::vec3& position, int deltaX, int deltaY);
|
||||
|
||||
private:
|
||||
bool _mousePressed;
|
||||
float _bodyPitchDelta;
|
||||
|
|
|
@ -546,6 +546,35 @@ glm::vec4 Model::computeAverageColor() const {
|
|||
return _geometry ? _geometry->computeAverageColor() : glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
const glm::vec3 relativeOrigin = origin - _translation;
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
float minDistance = FLT_MAX;
|
||||
float radiusScale = extractUniformScale(_scale);
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
glm::vec3 end = extractTranslation(_jointStates[i].transform);
|
||||
float endRadius = joint.boneRadius * radiusScale;
|
||||
glm::vec3 start = end;
|
||||
float startRadius = joint.boneRadius * radiusScale;
|
||||
if (joint.parentIndex != -1) {
|
||||
start = extractTranslation(_jointStates[joint.parentIndex].transform);
|
||||
startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale;
|
||||
}
|
||||
// for now, use average of start and end radii
|
||||
float capsuleDistance;
|
||||
if (findRayCapsuleIntersection(relativeOrigin, direction, start, end,
|
||||
(startRadius + endRadius) / 2.0f, capsuleDistance)) {
|
||||
minDistance = qMin(minDistance, capsuleDistance);
|
||||
}
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
distance = minDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||
glm::vec3& penetration, float boneScale, int skipIndex) const {
|
||||
const glm::vec3 relativeCenter = penetratorCenter - _translation;
|
||||
|
|
|
@ -125,6 +125,8 @@ public:
|
|||
/// Returns the average color of all meshes in the geometry.
|
||||
glm::vec4 computeAverageColor() const;
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||
glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const;
|
||||
|
||||
|
|
|
@ -154,6 +154,44 @@ glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3&
|
|||
newPenetration - (currentDirection * directionalComponent);
|
||||
}
|
||||
|
||||
bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& center, float radius, float& distance) {
|
||||
glm::vec3 relativeOrigin = origin - center;
|
||||
float b = glm::dot(direction, relativeOrigin);
|
||||
float c = glm::dot(relativeOrigin, relativeOrigin) - radius * radius;
|
||||
if (c < 0.0f) {
|
||||
distance = 0.0f;
|
||||
return true; // starts inside the sphere
|
||||
}
|
||||
float radicand = b * b - c;
|
||||
if (radicand < 0.0f) {
|
||||
return false; // doesn't hit the sphere
|
||||
}
|
||||
float t = -b - sqrtf(radicand);
|
||||
if (t < 0.0f) {
|
||||
return false; // doesn't hit the sphere
|
||||
}
|
||||
distance = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius, float& distance) {
|
||||
float minDistance = FLT_MAX;
|
||||
float sphereDistance;
|
||||
if (findRaySphereIntersection(origin, direction, start, radius, sphereDistance)) {
|
||||
minDistance = qMin(minDistance, sphereDistance);
|
||||
}
|
||||
if (findRaySphereIntersection(origin, direction, end, radius, sphereDistance)) {
|
||||
minDistance = qMin(minDistance, sphereDistance);
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
distance = minDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect?
|
||||
// from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html
|
||||
bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) {
|
||||
|
|
|
@ -49,6 +49,12 @@ bool findCapsulePlanePenetration(const glm::vec3& penetratorStart, const glm::ve
|
|||
|
||||
glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3& newPenetration);
|
||||
|
||||
bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& center, float radius, float& distance);
|
||||
|
||||
bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius, float& distance);
|
||||
|
||||
bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2);
|
||||
bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk);
|
||||
int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk);
|
||||
|
|
Loading…
Reference in a new issue