/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "TvAndDraggers.h" #include OdTvViewportParams::OdTvViewportParams() : fieldWidth(1.0), fieldHeight(1.0), projectionType(OdTvGsView::kParallel) {} void OdTvViewportParams::store(OdTvGsViewPtr pView) { position = pView->position(); target = pView->target(); up = pView->upVector(); fieldWidth = pView->fieldWidth(); fieldHeight = pView->fieldHeight(); projectionType = pView->isPerspective() ? OdTvGsView::kPerspective : OdTvGsView::kParallel; } void OdTvViewportParams::setup(OdTvExtendedView* pTvExtendedView) const { pTvExtendedView->setView(position, target, up, fieldWidth, fieldHeight, projectionType); } static void orbit(const OdTvViewportParams& params, double xOrbit, double yOrbit, const OdGePoint3d& viewCenter, OdTvExtendedView* pTvExtendedView) { OdTvViewportParams rotatedParams = params; // compute camera side vector OdGeVector3d side = rotatedParams.up.crossProduct(rotatedParams.target - rotatedParams.position).normalize(); double angle = sqrt(yOrbit * yOrbit + xOrbit * xOrbit); OdGeVector3d axis = (rotatedParams.up * yOrbit - side * xOrbit).normalize(); rotatedParams.position.rotateBy(angle, axis, viewCenter); rotatedParams.target.rotateBy(angle, axis, viewCenter); if (yOrbit != 0.0) { side = side.rotateBy(angle, axis); } // update up vector rotatedParams.up = (rotatedParams.target - rotatedParams.position).crossProduct(side).normalize(); rotatedParams.setup(pTvExtendedView); } static double screenSize(OdTvGsViewPtr pView) { OdTvDCRect viewportRect; pView->getViewport(viewportRect); OdGePoint2d screenSize(Od_abs(viewportRect.xmax - viewportRect.xmin), Od_abs(viewportRect.ymax - viewportRect.ymin)); return odmax(screenSize.x, screenSize.y); } //////////////////////////////////////////// ////// TvAndBaseDragger implementation /////// //////////////////////////////////////////// eDraggerResult TvAndBaseDragger::drag(int x, int y) { if (!m_bFixedFrameRateEnabled && m_pGlobalParams && m_pGlobalParams->getFixedFrameRate()) { OdTvGsViewPtr pView = getActiveTvViewPtr(); if (!pView.isNull()) { if (pView->isInInteractivity()) pView->endInteractivity(); pView->beginInteractivity(m_pGlobalParams->getFpsValue()); m_bFixedFrameRateEnabled = true; } } return kNothingToDo; } eDraggerResult TvAndBaseDragger::nextpointup(int x, int y) { if (m_bFixedFrameRateEnabled && m_pGlobalParams && m_pGlobalParams->getFixedFrameRate()) { OdTvGsViewPtr pView = getActiveTvViewPtr(); if (!pView.isNull() && pView->isInInteractivity()) { pView->endInteractivity(); m_bFixedFrameRateEnabled = false; if (!m_TvDeviceId.isNull()) { OdTvGsDevicePtr pDev = m_TvDeviceId.openObject(OdTv::kForWrite); pDev->invalidate(); } } } return kNothingToDo; } //////////////////////////////////////////// ////// TvAndPanDragger implementation //////// //////////////////////////////////////////// eDraggerResult TvAndPanDragger::start(OdTvDraggerPtr pPrevDragger, OdTvExtendedView *pExtendedView) { return OdTvDragger::start(pPrevDragger, pExtendedView); } eDraggerResult TvAndPanDragger::nextpoint(int x, int y) { if ( m_state == kWaiting ) return kNothingToDo; OdTvGsViewPtr pView = getActiveTvViewPtr(); if ( pView.isNull() ) return kNothingToDo; // remember camera current position m_pos = pView->position(); // remember the difference between click point in WCS and camera current position m_prevPt = toEyeToWorld(x, y) - m_pos.asVector(); return kNothingToDo; } eDraggerResult TvAndPanDragger::drag(int x, int y) { if ( m_state == kWaiting ) return kNothingToDo; OdTvGsViewPtr pView = getActiveTvViewPtr(); if ( pView.isNull() ) return kNothingToDo; // enable frame rate, if need TvAndBaseDragger::drag(x, y); // calculate click point in WCS OdGePoint3d pt = toEyeToWorld(x, y); //obtain delta for dolly OdGeVector3d delta = (m_prevPt - (pt - m_pos)).asVector(); // transform delta to eye delta.transformBy(pView->viewingMatrix()); // perform camera moving pView->dolly(delta.x, delta.y, delta.z); // remember the difference between click point in WCS and camera previous position m_prevPt = pt - m_pos.asVector(); // remember camera current position m_pos = pView->position(); return kNeedUpdateView; } eDraggerResult TvAndPanDragger::nextpointup(int x, int y) { // off fixed frame rate mode TvAndBaseDragger::nextpointup(x, y); return reset(); } //////////////////////////////////////////// ///// TvAndOrbitDragger implementation /////// //////////////////////////////////////////// TvAndOrbitDragger::TvAndOrbitDragger(OdTvGsDeviceId &tvDeviceId, OdTvModelId &tvDraggersModelId, TvAndGlobalParameters* pParams) : TvAndBaseDragger (tvDeviceId, tvDraggersModelId, pParams) { } eDraggerResult TvAndOrbitDragger::start(OdTvDraggerPtr pPrevDragger, OdTvExtendedView *pExtendedView) { return OdTvDragger::start(pPrevDragger, pExtendedView); } eDraggerResult TvAndOrbitDragger::nextpoint(int x, int y) { if ( m_state == kWaiting ) return kNothingToDo; OdTvGsViewPtr pView = getActiveTvViewPtr(); if ( pView.isNull() ) return kNothingToDo; m_viewportParams.store(pView); m_startCursorPosition = OdTvDCPoint(x, y); if (m_pTvExtendedView) { OdGeBoundBlock3d lastExt; if (pView->getLastViewExtents(lastExt)) m_pTvExtendedView->setViewExtentsForCaching(&lastExt); } return kNothingToDo; } eDraggerResult TvAndOrbitDragger::drag(int x, int y) { if ( m_state == kWaiting ) return kNothingToDo; OdTvGsViewPtr pView = getActiveTvViewPtr(); if ( pView.isNull() ) return kNothingToDo; // enable frame rate, if need TvAndBaseDragger::drag(x, y); double size = screenSize(pView); m_viewportParams.setup(m_pTvExtendedView); // calculate the angles for the rotation about appropriate axes double distX = (m_startCursorPosition.x - x) * OdaPI / size; double distY = (m_startCursorPosition.y - y) * OdaPI / size; // perform camera orbiting double xOrbit = distY; double yOrbit = distX; if (xOrbit != 0.0 || yOrbit != 0.0) { OdGeBoundBlock3d lastExt; m_pTvExtendedView->getCachedExtents(lastExt); orbit(m_viewportParams, xOrbit, yOrbit, lastExt.center(), m_pTvExtendedView); } return kNeedUpdateView; } eDraggerResult TvAndOrbitDragger::nextpointup(int x, int y) { // off fixed frame rate mode TvAndBaseDragger::nextpointup(x, y); return reset(); }