PointerEvent ParabolaPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button, bool hover) { QUuid pickedID; glm::vec3 intersection, surfaceNormal, origin, velocity, acceleration; auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult); if (parabolaPickResult) { intersection = parabolaPickResult->intersection; surfaceNormal = parabolaPickResult->surfaceNormal; const QVariantMap& parabola = parabolaPickResult->pickVariant; origin = vec3FromVariant(parabola["origin"]); velocity = vec3FromVariant(parabola["velocity"]); acceleration = vec3FromVariant(parabola["acceleration"]); pickedID = parabolaPickResult->objectID; } if (pickedID != target.objectID) { intersection = findIntersection(target, origin, velocity, acceleration); } glm::vec2 pos2D = findPos2D(target, intersection); // If we just started triggering and we haven't moved too much, don't update intersection and pos2D TriggerState& state = hover ? _latestState : _states[button]; float sensorToWorldScale = DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale(); float deadspotSquared = TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED * sensorToWorldScale * sensorToWorldScale; bool withinDeadspot = usecTimestampNow() - state.triggerStartTime < POINTER_MOVE_DELAY && glm::distance2(pos2D, state.triggerPos2D) < deadspotSquared; if ((state.triggering || state.wasTriggering) && !state.deadspotExpired && withinDeadspot) { pos2D = state.triggerPos2D; intersection = state.intersection; surfaceNormal = state.surfaceNormal; } if (!withinDeadspot) { state.deadspotExpired = true; } return PointerEvent(pos2D, intersection, surfaceNormal, velocity); }
void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getWorldPosition(); auto origRotation = getWorldOrientation(); auto origDimensions = getDimensions(); auto origScale = getSNScale(); Base3DOverlay::setProperties(properties); auto scale = properties["scale"]; if (scale.isValid()) { setSNScale(vec3FromVariant(scale)); } auto dimensions = properties["dimensions"]; if (!dimensions.isValid()) { dimensions = properties["size"]; } if (dimensions.isValid()) { _scaleToFit = true; setDimensions(vec3FromVariant(dimensions)); } else if (scale.isValid()) { // if "scale" property is set but "dimensions" is not. // do NOT scale to fit. _scaleToFit = false; } if (origPosition != getWorldPosition() || origRotation != getWorldOrientation() || origDimensions != getDimensions() || origScale != getSNScale()) { _updateModel = true; } auto loadPriorityProperty = properties["loadPriority"]; if (loadPriorityProperty.isValid()) { _loadPriority = loadPriorityProperty.toFloat(); _model->setLoadingPriority(_loadPriority); } auto urlValue = properties["url"]; if (urlValue.isValid() && urlValue.canConvert<QString>()) { _url = urlValue.toString(); _updateModel = true; _isLoaded = false; _texturesLoaded = false; } auto texturesValue = properties["textures"]; if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) { _texturesLoaded = false; QVariantMap textureMap = texturesValue.toMap(); QMetaObject::invokeMethod(_model.get(), "setTextures", Qt::AutoConnection, Q_ARG(const QVariantMap&, textureMap)); }
void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getPosition(); auto origRotation = getRotation(); auto origDimensions = getDimensions(); auto origScale = getScale(); Base3DOverlay::setProperties(properties); auto scale = properties["scale"]; if (scale.isValid()) { setScale(vec3FromVariant(scale)); } auto dimensions = properties["dimensions"]; if (dimensions.isValid()) { _scaleToFit = true; setDimensions(vec3FromVariant(dimensions)); } else if (scale.isValid()) { // if "scale" property is set but "dimentions" is not. // do NOT scale to fit. _scaleToFit = false; } if (origPosition != getPosition() || origRotation != getRotation() || origDimensions != getDimensions() || origScale != getScale()) { _updateModel = true; } auto urlValue = properties["url"]; if (urlValue.isValid() && urlValue.canConvert<QString>()) { _url = urlValue.toString(); _updateModel = true; _isLoaded = false; } auto texturesValue = properties["textures"]; if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) { QVariantMap textureMap = texturesValue.toMap(); foreach(const QString& key, textureMap.keys()) { QUrl newTextureURL = textureMap[key].toUrl(); qDebug() << "Updating texture named" << key << "to texture at URL" << newTextureURL; QMetaObject::invokeMethod(_model.get(), "setTextureWithNameToURL", Qt::AutoConnection, Q_ARG(const QString&, key), Q_ARG(const QUrl&, newTextureURL)); _modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty() } }
void Volume3DOverlay::setProperties(const QVariantMap& properties) { Base3DOverlay::setProperties(properties); auto dimensions = properties["dimensions"]; // if "dimensions" property was not there, check to see if they included aliases: scale, size if (!dimensions.isValid()) { dimensions = properties["scale"]; if (!dimensions.isValid()) { dimensions = properties["size"]; } } if (dimensions.isValid()) { glm::vec3 scale = vec3FromVariant(dimensions); // don't allow a zero or negative dimension component to reach the renderTransform const float MIN_DIMENSION = 0.0001f; if (scale.x < MIN_DIMENSION) { scale.x = MIN_DIMENSION; } if (scale.y < MIN_DIMENSION) { scale.y = MIN_DIMENSION; } if (scale.z < MIN_DIMENSION) { scale.z = MIN_DIMENSION; } setDimensions(scale); } }
glm::vec2 RayPick::projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos, bool unNormalized) { glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value); glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value); glm::vec3 dimensions = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "dimensions").value), 0.01f); return projectOntoXYPlane(worldPos, position, rotation, dimensions, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT, unNormalized); }
void Line3DOverlay::setProperties(const QVariantMap& properties) { Base3DOverlay::setProperties(properties); auto start = properties["start"]; // if "start" property was not there, check to see if they included aliases: startPoint if (!start.isValid()) { start = properties["startPoint"]; } if (start.isValid()) { setStart(vec3FromVariant(start)); } auto end = properties["end"]; // if "end" property was not there, check to see if they included aliases: endPoint if (!end.isValid()) { end = properties["endPoint"]; } if (end.isValid()) { setEnd(vec3FromVariant(end)); } }
/**jsdoc * <p>An RGB or SRGB color value.</p> * <table> * <thead> * <tr><th>Index</th><th>Type</th><th>Attributes</th><th>Default</th><th>Value</th></tr> * </thead> * <tbody> * <tr><td><code>0</code></td><td>number</td><td></td><td></td> * <td>Red component value. Number in the range <code>0.0</code> – <code>1.0</code>.</td></tr> * <tr><td><code>1</code></td><td>number</td><td></td><td></td> * <td>Green component value. Number in the range <code>0.0</code> – <code>1.0</code>.</td></tr> * <tr><td><code>2</code></td><td>number</td><td></td><td></td> * <td>Blue component value. Number in the range <code>0.0</code> – <code>1.0</code>.</td></tr> * <tr><td><code>3</code></td><td>boolean</td><td><optional></td><td>false</td> * <td>If <code>true</code> then the color is an SRGB color.</td></tr> * </tbody> * </table> * @typedef {array} RGBS */ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB) { if (array.isArray()) { QJsonArray colorArray = array.toArray(); if (colorArray.size() >= 3 && colorArray[0].isDouble() && colorArray[1].isDouble() && colorArray[2].isDouble()) { isSRGB = true; if (colorArray.size() >= 4) { if (colorArray[3].isBool()) { isSRGB = colorArray[3].toBool(); } } color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble()); return true; } } else if (array.isObject()) { bool toReturn; isSRGB = true; color = vec3FromVariant(array.toObject(), toReturn); return toReturn; } return false; }
glm::vec3 vec3FromVariant(const QVariant &object) { bool valid = false; return vec3FromVariant(object, valid); }
glm::vec3 RayPick::intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction) { glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value); glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value); return intersectRayWithXYPlane(origin, direction, position, rotation, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT); }
void Base3DOverlay::setProperties(const QVariantMap& properties) { Overlay::setProperties(properties); bool needRenderItemUpdate = false; auto drawInFront = properties["drawInFront"]; if (drawInFront.isValid()) { bool value = drawInFront.toBool(); setDrawInFront(value); needRenderItemUpdate = true; } auto position = properties["position"]; // if "position" property was not there, check to see if they included aliases: point, p1 if (!position.isValid()) { position = properties["p1"]; if (!position.isValid()) { position = properties["point"]; } } if (position.isValid()) { setPosition(vec3FromVariant(position)); needRenderItemUpdate = true; } if (properties["lineWidth"].isValid()) { setLineWidth(properties["lineWidth"].toFloat()); needRenderItemUpdate = true; } auto rotation = properties["rotation"]; if (rotation.isValid()) { setRotation(quatFromVariant(rotation)); needRenderItemUpdate = true; } if (properties["isSolid"].isValid()) { setIsSolid(properties["isSolid"].toBool()); } if (properties["isFilled"].isValid()) { setIsSolid(properties["isSolid"].toBool()); } if (properties["isWire"].isValid()) { setIsSolid(!properties["isWire"].toBool()); } if (properties["solid"].isValid()) { setIsSolid(properties["solid"].toBool()); } if (properties["filled"].isValid()) { setIsSolid(properties["filled"].toBool()); } if (properties["wire"].isValid()) { setIsSolid(!properties["wire"].toBool()); } if (properties["isDashedLine"].isValid()) { setIsDashedLine(properties["isDashedLine"].toBool()); } if (properties["dashed"].isValid()) { setIsDashedLine(properties["dashed"].toBool()); } if (properties["ignoreRayIntersection"].isValid()) { setIgnoreRayIntersection(properties["ignoreRayIntersection"].toBool()); } // Communicate changes to the renderItem if needed if (needRenderItemUpdate) { auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::PendingChanges pendingChanges; pendingChanges.updateItem(itemID); scene->enqueuePendingChanges(pendingChanges); } } }
glm::vec3 ParabolaPointer::getPickOrigin(const PickResultPointer& pickResult) const { auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult); return (parabolaPickResult ? vec3FromVariant(parabolaPickResult->pickVariant["origin"]) : glm::vec3(0.0f)); }