void JX3DWidget::ContinueDrag ( const JPoint& pt ) { if (itsDragType == kRotateDrag) { const JVector delta(3, - pt.x + itsStartPt.x, pt.y - itsStartPt.y, 0.0); const JVector& o = itsCamera->GetAttentionPt(); JVector v = itsStartPos - o; const JFloat r = v.GetLength(); const JFloat lat = asin(v.GetElement(3) / r); const JFloat lon = atan2(v.GetElement(2), v.GetElement(1)); // direction of drag relative to screen x-axis const JFloat alpha = atan2(delta.GetElement(2), delta.GetElement(1)); // delta along the sphere in drag direction const JFloat phi = delta.GetLength() / (r * 50); JVector p(3, r*cos(phi), r*sin(phi), 0.0); // inverse: rotate around z-axis for partial alignment of x-axis JMatrix r1(3, 3); r1.SetElements( cos(lon), -sin(lon), 0.0, sin(lon), cos(lon), 0.0, 0.0, 0.0, 1.0); // inverse: rotate around y-axis for complete alignment of x-axis towards viewer JMatrix r2(3, 3); r2.SetElements( cos(lat), 0.0, -sin(lat), 0.0, 1.0, 0.0, sin(lat), 0.0, cos(lat)); // inverse: rotate around x-axis to align y-axis with drag direction JMatrix r3(3, 3); r3.SetElements( 1.0, 0.0, 0.0, 0.0, cos(alpha), -sin(alpha), 0.0, sin(alpha), cos(alpha)); // transform delta long the sphere to our coordinate system p = (r1 * r2 * r3 * p).GetColVector(1); itsCamera->SetPosition(p + o); } }
JBoolean JX3DWidget::HandleRotationKeyPress ( const int key, const JXKeyModifiers& modifiers ) { if (modifiers.meta() && key == kJUpArrow) { return ZoomForWheel(kJXButton4, modifiers); } else if (modifiers.meta() && key == kJDownArrow) { return ZoomForWheel(kJXButton5, modifiers); } const JVector& o = itsCamera->GetAttentionPt(); JVector v = itsCamera->GetPosition() - o; const JFloat r = v.GetLength(); JFloat lat = asin(v.GetElement(3) / r); JFloat lon = atan2(v.GetElement(2), v.GetElement(1)); const JFloat delta = (modifiers.shift() ? kSmallDeltaAngle : (modifiers.control() ? kBigDeltaAngle : kDeltaAngle)); JBoolean moved = kJFalse; if (key == kJUpArrow) { lat += delta; moved = kJTrue; } else if (key == kJDownArrow) { lat -= delta; moved = kJTrue; } else if (key == kJLeftArrow) { lon += delta; moved = kJTrue; } else if (key == kJRightArrow) { lon -= delta; moved = kJTrue; } if (moved) { itsCamera->SetPosition(JVector(3, r * cos(lat) * cos(lon), r * cos(lat) * sin(lon), r * sin(lat))); Redraw(); // key repeats can delay Refresh() return kJTrue; } else { return kJFalse; } }