181 lines · 7.8 KB · Text
RawDownload
////  Created by Sam Gondelman on 1/22/19//  Copyright 2019 High Fidelity, Inc.//  Copyright 2023 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  SPDX-License-Identifier: Apache-2.0// #include "GizmoEntityItem.h" #include "EntityItemProperties.h" #include <qmath.h> EntityItemPointer GizmoEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {    Pointer entity(new GizmoEntityItem(entityID), [](GizmoEntityItem* ptr) { ptr->deleteLater(); });    entity->setProperties(properties);    return entity;} // our non-pure virtual subclass for now...GizmoEntityItem::GizmoEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {    _type = EntityTypes::Gizmo;    _gizmoType = GizmoType::UNSET_GIZMO_TYPE;} void GizmoEntityItem::setUnscaledDimensions(const glm::vec3& value) {    // NOTE: Gizmo Entities always have a "height" of 1mm.    EntityItem::setUnscaledDimensions(glm::vec3(value.x, ENTITY_ITEM_MIN_DIMENSION, value.z));} EntityItemProperties GizmoEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {    EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class @Gizmo_ENTITY_COPY_TO@     return properties;} bool GizmoEntityItem::setSubClassProperties(const EntityItemProperties& properties) {    bool somethingChanged = false; @Gizmo_ENTITY_SET_FROM@     return somethingChanged;} EntityPropertyFlags GizmoEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {    EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); @Gizmo_REQUESTED_PROPS@     return requestedProperties;} void GizmoEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,                                         EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,                                         EntityPropertyFlags& requestedProperties,                                         EntityPropertyFlags& propertyFlags,                                         EntityPropertyFlags& propertiesDidntFit,                                         int& propertyCount,                                         OctreeElement::AppendState& appendState) const {     bool successPropertyFits = true; @Gizmo_ENTITY_APPEND@ } int GizmoEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,                                                ReadBitstreamToTreeParams& args,                                                EntityPropertyFlags& propertyFlags, bool overwriteLocalData,                                                bool& somethingChanged) {     int bytesRead = 0;    const unsigned char* dataAt = data; @Gizmo_ENTITY_READ@     return bytesRead;} void GizmoEntityItem::debugDump() const {    qCDebug(entities) << "GizmoEntityItem id:" << getEntityItemID() << "---------------------------------------------";    qCDebug(entities) << "    name:" << _name;    qCDebug(entities) << "    position:" << debugTreeVector(getWorldPosition());    qCDebug(entities) << "    dimensions:" << debugTreeVector(getScaledDimensions());    qCDebug(entities) << "    editedAgo:" << debugTime(getLastEdited(), usecTimestampNow());    qCDebug(entities) << "    pointer:" << this; @Gizmo_ENTITY_DEBUG@ } bool GizmoEntityItem::supportsDetailedIntersection() const {    return _gizmoType == GizmoType::RING;} bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,                                                  const glm::vec3& viewFrustumPos, OctreeElementPointer& element,                                                  float& distance, BoxFace& face, glm::vec3& surfaceNormal,                                                  QVariantMap& extraInfo, bool precisionPicking) const {    glm::vec3 dimensions = getScaledDimensions();    glm::vec2 xyDimensions(dimensions.x, dimensions.z);    BillboardMode billboardMode = getBillboardMode();    glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();    rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT);    glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));    rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);     if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) {        glm::vec3 hitPosition = origin + (distance * direction);        glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - getWorldPosition());        localHitPosition.x /= xyDimensions.x;        localHitPosition.y /= xyDimensions.y;        float distanceToHit = glm::length(localHitPosition);         if (0.5f * _ringProperties.getInnerRadius() <= distanceToHit && distanceToHit <= 0.5f) {            glm::vec3 forward = rotation * Vectors::FRONT;            if (glm::dot(forward, direction) > 0.0f) {                face = MAX_Z_FACE;                surfaceNormal = -forward;            } else {                face = MIN_Z_FACE;                surfaceNormal = forward;            }            return true;        }    }     return false;} bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,                                                       const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance,                                                       BoxFace& face, glm::vec3& surfaceNormal,                                                       QVariantMap& extraInfo, bool precisionPicking) const {    //// Scale the dimensions by the diameter    glm::vec3 dimensions = getScaledDimensions();    glm::vec2 xyDimensions(dimensions.x, dimensions.z);    BillboardMode billboardMode = getBillboardMode();    glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();    rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT);    glm::vec3 position = getWorldPosition();    rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);     glm::quat inverseRot = glm::inverse(rotation);    glm::vec3 localOrigin = inverseRot * (origin - position);    glm::vec3 localVelocity = inverseRot * velocity;    glm::vec3 localAcceleration = inverseRot * acceleration;     if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) {        glm::vec3 localHitPosition = localOrigin + localVelocity * parabolicDistance + 0.5f * localAcceleration * parabolicDistance * parabolicDistance;        localHitPosition.x /= xyDimensions.x;        localHitPosition.y /= xyDimensions.y;        float distanceToHit = glm::length(localHitPosition);         if (0.5f * _ringProperties.getInnerRadius() <= distanceToHit && distanceToHit <= 0.5f) {            float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance;            glm::vec3 forward = rotation * Vectors::FRONT;            if (localIntersectionVelocityZ > 0.0f) {                face = MIN_Z_FACE;                surfaceNormal = forward;            } else {                face = MAX_Z_FACE;                surfaceNormal = -forward;            }            return true;        }    }     return false;} RingGizmoPropertyGroup GizmoEntityItem::getRingProperties() const {    return resultWithReadLock<RingGizmoPropertyGroup>([&] {        return _ringProperties;    });}