//[-------------------------------------------------------] //[ Private virtual PLScene::SNMTransformGizmo functions ] //[-------------------------------------------------------] void SNMTransformGizmoRotationController::UpdateSelection(Renderer &cRenderer, const VisNode &cVisNode) { // Get the frontend instance Frontend &cFrontend = static_cast<FrontendApplication*>(CoreApplication::GetApplication())->GetFrontend(); // Check whether or not the mouse is currently over the frontend if (cFrontend.IsMouseOver()) { // Get current mouse cursor position inside the widget const int nMousePosX = cFrontend.GetMousePositionX(); const int nMousePosY = cFrontend.GetMousePositionY(); // Calculate the clip space to object space matrix Matrix4x4 mClipSpaceToObjectSpace = m_mObjectSpaceToClipSpace; mClipSpaceToObjectSpace.Invert(); // Check where the mouse is over // Get the ray starting from the camera position in direction of the mouse position Vector3 v2DPos(static_cast<float>(nMousePosX), static_cast<float>(nMousePosY), 0.0001f); Vector3 vCamPos = v2DPos.To3DCoordinate(mClipSpaceToObjectSpace, cRenderer.GetViewport()); v2DPos.z = 0.9999f; Vector3 vEndPos = v2DPos.To3DCoordinate(mClipSpaceToObjectSpace, cRenderer.GetViewport()); // Determine the current selected axis by using a picking ray Ray cRay; cRay.Set(vCamPos, vEndPos); m_nSelected = DetermineSelected(cRay); } else { m_nSelected = 0; } }
void VRDisplayOpenVR::UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms /* = nullptr */) { // Note this must be called every frame, as the IPD adjustment can be changed // by the user during a VR session. for (uint32_t eye = 0; eye < VRDisplayState::NumEyes; eye++) { ::vr::HmdMatrix34_t eyeToHead = mVRSystem->GetEyeToHeadTransform(static_cast<::vr::Hmd_Eye>(eye)); mDisplayInfo.mDisplayState.mEyeTranslation[eye].x = eyeToHead.m[0][3]; mDisplayInfo.mDisplayState.mEyeTranslation[eye].y = eyeToHead.m[1][3]; mDisplayInfo.mDisplayState.mEyeTranslation[eye].z = eyeToHead.m[2][3]; if (aHeadToEyeTransforms) { Matrix4x4 pose; // NOTE! eyeToHead.m is a 3x4 matrix, not 4x4. But // because of its arrangement, we can copy the 12 elements in and // then transpose them to the right place. memcpy(&pose._11, &eyeToHead.m, sizeof(eyeToHead.m)); pose.Transpose(); pose.Invert(); aHeadToEyeTransforms[eye] = pose; } } }
void LayerManagerComposite::PostProcessLayers(Layer* aLayer, nsIntRegion& aOpaqueRegion, LayerIntRegion& aVisibleRegion, const Maybe<ParentLayerIntRect>& aClipFromAncestors) { if (aLayer->Extend3DContext()) { // For layers participating 3D rendering context, their visible // region should be empty (invisible), so we pass through them // without doing anything. // Direct children of the establisher may have a clip, becaue the // item containing it; ex. of nsHTMLScrollFrame, may give it one. Maybe<ParentLayerIntRect> layerClip = aLayer->AsHostLayer()->GetShadowClipRect(); Maybe<ParentLayerIntRect> ancestorClipForChildren = IntersectMaybeRects(layerClip, aClipFromAncestors); MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(), "Only direct children of the establisher could have a clip"); for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { PostProcessLayers(child, aOpaqueRegion, aVisibleRegion, ancestorClipForChildren); } return; } nsIntRegion localOpaque; // Treat layers on the path to the root of the 3D rendering context as // a giant layer if it is a leaf. Matrix4x4 transform = GetAccTransformIn3DContext(aLayer); Matrix transform2d; Maybe<IntPoint> integerTranslation; // If aLayer has a simple transform (only an integer translation) then we // can easily convert aOpaqueRegion into pre-transform coordinates and include // that region. if (transform.Is2D(&transform2d)) { if (transform2d.IsIntegerTranslation()) { integerTranslation = Some(IntPoint::Truncate(transform2d.GetTranslation())); localOpaque = aOpaqueRegion; localOpaque.MoveBy(-*integerTranslation); } } // Compute a clip that's the combination of our layer clip with the clip // from our ancestors. LayerComposite* composite = static_cast<LayerComposite*>(aLayer->AsHostLayer()); Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect(); MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(), "The layer with a clip should not participate " "a 3D rendering context"); Maybe<ParentLayerIntRect> outsideClip = IntersectMaybeRects(layerClip, aClipFromAncestors); // Convert the combined clip into our pre-transform coordinate space, so // that it can later be intersected with our visible region. // If our transform is a perspective, there's no meaningful insideClip rect // we can compute (it would need to be a cone). Maybe<LayerIntRect> insideClip; if (outsideClip && !transform.HasPerspectiveComponent()) { Matrix4x4 inverse = transform; if (inverse.Invert()) { Maybe<LayerRect> insideClipFloat = UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(inverse), ParentLayerRect(*outsideClip), LayerRect::MaxIntRect()); if (insideClipFloat) { insideClipFloat->RoundOut(); LayerIntRect insideClipInt; if (insideClipFloat->ToIntRect(&insideClipInt)) { insideClip = Some(insideClipInt); } } } } Maybe<ParentLayerIntRect> ancestorClipForChildren; if (insideClip) { ancestorClipForChildren = Some(ViewAs<ParentLayerPixel>(*insideClip, PixelCastJustification::MovingDownToChildren)); } // Save the value of localOpaque, which currently stores the region obscured // by siblings (and uncles and such), before our descendants contribute to it. nsIntRegion obscured = localOpaque; // Recurse on our descendants, in front-to-back order. In this process: // - Occlusions are computed for them, and they contribute to localOpaque. // - They recalculate their visible regions, taking ancestorClipForChildren // into account, and accumulate them into descendantsVisibleRegion. LayerIntRegion descendantsVisibleRegion; bool hasPreserve3DChild = false; for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { PostProcessLayers(child, localOpaque, descendantsVisibleRegion, ancestorClipForChildren); if (child->Extend3DContext()) { hasPreserve3DChild = true; } } // Recalculate our visible region. LayerIntRegion visible = composite->GetShadowVisibleRegion(); // If we have descendants, throw away the visible region stored on this // layer, and use the region accumulated by our descendants instead. if (aLayer->GetFirstChild() && !hasPreserve3DChild) { visible = descendantsVisibleRegion; } // Subtract any areas that we know to be opaque. if (!obscured.IsEmpty()) { visible.SubOut(LayerIntRegion::FromUnknownRegion(obscured)); } // Clip the visible region using the combined clip. if (insideClip) { visible.AndWith(*insideClip); } composite->SetShadowVisibleRegion(visible); // Transform the newly calculated visible region into our parent's space, // apply our clip to it (if any), and accumulate it into |aVisibleRegion| // for the caller to use. ParentLayerIntRegion visibleParentSpace = TransformBy( ViewAs<LayerToParentLayerMatrix4x4>(transform), visible); if (const Maybe<ParentLayerIntRect>& clipRect = composite->GetShadowClipRect()) { visibleParentSpace.AndWith(*clipRect); } aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace, PixelCastJustification::MovingDownToChildren)); // If we have a simple transform, then we can add our opaque area into // aOpaqueRegion. if (integerTranslation && !aLayer->HasMaskLayers() && aLayer->IsOpaqueForVisibility()) { if (aLayer->IsOpaque()) { localOpaque.OrWith(composite->GetFullyRenderedRegion()); } localOpaque.MoveBy(*integerTranslation); if (layerClip) { localOpaque.AndWith(layerClip->ToUnknownRect()); } aOpaqueRegion.OrWith(localOpaque); } }
void Node::SetTransformation(const Matrix4x4& transformation) { transformation_ = transformation; transformation_inverse_ = transformation.Invert(); }
static void ApplyAsyncTransformToScrollbarForContent(ContainerLayer* aScrollbar, Layer* aContent, bool aScrollbarIsChild) { // We only apply the transform if the scroll-target layer has non-container // children (i.e. when it has some possibly-visible content). This is to // avoid moving scroll-bars in the situation that only a scroll information // layer has been built for a scroll frame, as this would result in a // disparity between scrollbars and visible content. if (aContent->AsContainerLayer() && !LayerHasNonContainerDescendants(aContent->AsContainerLayer())) { return; } const FrameMetrics& metrics = aContent->GetFrameMetrics(); AsyncPanZoomController* apzc = aContent->GetAsyncPanZoomController(); Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform(); Matrix4x4 nontransientTransform = apzc->GetNontransientAsyncTransform(); Matrix4x4 nontransientUntransform = nontransientTransform; nontransientUntransform.Invert(); Matrix4x4 transientTransform = asyncTransform * nontransientUntransform; // |transientTransform| represents the amount by which we have scrolled and // zoomed since the last paint. Because the scrollbar was sized and positioned based // on the painted content, we need to adjust it based on transientTransform so that // it reflects what the user is actually seeing now. // - The scroll thumb needs to be scaled in the direction of scrolling by the inverse // of the transientTransform scale (representing the zoom). This is because zooming // in decreases the fraction of the whole scrollable rect that is in view. // - It needs to be translated in opposite direction of the transientTransform // translation (representing the scroll). This is because scrolling down, which // translates the layer content up, should result in moving the scroll thumb down. // The amount of the translation to the scroll thumb should be such that the ratio // of the translation to the size of the scroll port is the same as the ratio // of the scroll amount to the size of the scrollable rect. Matrix4x4 scrollbarTransform; if (aScrollbar->GetScrollbarDirection() == Layer::VERTICAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().height / metrics.mScrollableRect.height; scrollbarTransform = scrollbarTransform * Matrix4x4().Scale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform = scrollbarTransform * Matrix4x4().Translate(0, -transientTransform._42 * scale, 0); } if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; scrollbarTransform = scrollbarTransform * Matrix4x4().Scale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform = scrollbarTransform * Matrix4x4().Translate(-transientTransform._41 * scale, 0, 0); } Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform(); if (aScrollbarIsChild) { // If the scrollbar layer is a child of the content it is a scrollbar for, then we // need to do an extra untransform to cancel out the transient async transform on // the content. This is needed because otherwise that transient async transform is // part of the effective transform of this scrollbar, and the scrollbar will jitter // as the content scrolls. transientTransform.Invert(); transform = transform * transientTransform; } // GetTransform already takes the pre- and post-scale into account. Since we // will apply the pre- and post-scale again when computing the effective // transform, we must apply the inverses here. transform.Scale(1.0f/aScrollbar->GetPreXScale(), 1.0f/aScrollbar->GetPreYScale(), 1); transform = transform * Matrix4x4().Scale(1.0f/aScrollbar->GetPostXScale(), 1.0f/aScrollbar->GetPostYScale(), 1); aScrollbar->AsLayerComposite()->SetShadowTransform(transform); }