Showing Objects Transforming Dynamically
Windows only

Overview

The CRhinoViewport class has two member functions, GetModelXform() and SetModelXform(), that either retrieve or modify the model transformation matrix that is applied to objects before they are drawn. The model transformation matrix is intended to be used for dynamic drawing of objects. Note, the default model transformation matrix is the identity.

Some of the Rhino command that use this technique to dynamically draw transforming objects include the Move, Copy, Scale, and Rotate commands. These commands derive new CRhinoGetPoint classes and override the virtual DynamicDraw() member function to draw objects dynamically as the mouse moves during a point picking operation.

Sample

The following is an sample CRhinoGetPoint-derived class that demonstrates how to dynamically draw transforming objects during a point picking operation. In this sample, the transformation is a simple translation, like used in the Move command.

First, the class declaration…

////////////////////////////////////////////////////////////////////
// CRhinoGetTranslationPoint declaration

class CRhinoGetTranslationPoint : public CRhinoGetPoint
{
public:

  CRhinoGetTranslationPoint();
  ~CRhinoGetTranslationPoint() {}

  // CRhinoGetPoint overrides  
  void SetBasePoint( ON_3dPoint base_point, BOOL bShowDistanceInStatusBar = false );
  void OnMouseMove( CRhinoViewport& vp, UINT flags, const ON_3dPoint& pt, const CPoint* p );
  void DynamicDraw( HDC hdc, CRhinoViewport& vp, const ON_3dPoint& pt );

  // Additional helpers
  void AddObject( const CRhinoObject* object );
  void CalculateTranslation( const ON_3dPoint& pt, ON_Xform& xform );

private:
  ON_3dPoint m_start_point; // starting point of translation
  ON_Xform m_xform; // transformation matrix
  ON_SimpleArray<const CRhinoObject*> m_objects; //objects to transform
};

////////////////////////////////////////////////////////////////////
// CRhinoGetTranslationPoint definition

CRhinoGetTranslationPoint::CRhinoGetTranslationPoint()
{
  m_xform.Identity();
}

void CRhinoGetTranslationPoint::AddObject( const CRhinoObject* object )
{
  m_objects.Append( object );
}

void CRhinoGetTranslationPoint::SetBasePoint(
      ON_3dPoint base_point,
      BOOL bShowDistanceInStatusBar
      )
{
  m_start_point = base_point;
  CRhinoGetPoint::SetBasePoint( base_point, bShowDistanceInStatusBar );
}

void CRhinoGetTranslationPoint::CalculateTranslation(
      const ON_3dPoint& pt,
      ON_Xform& xform
      )
{
  ON_3dVector v = pt - m_start_point;
  if( v.IsTiny() )
    xform.Identity();
  else
    xform.Translation( v );
}

void CRhinoGetTranslationPoint::OnMouseMove(
     CRhinoViewport& vp,
     UINT flags,
     const ON_3dPoint& pt,
     const CPoint* p
     )
{
  // Everytime the mouse moves, calculate the translation
  CalculateTranslation( pt, m_xform );
  CRhinoGetPoint::OnMouseMove( vp, flags, pt, p );
}

void CRhinoGetTranslationPoint::DynamicDraw(
     HDC hdc,
     CRhinoViewport& vp,
     const ON_3dPoint& pt
     )
{
  // Time to draw our objects dynamically
  int i, count = m_objects.Count();
  if( m_xform.IsIdentity() == false && count > 0 )
  {
    ON_Color saved_color = vp.DrawColor();
    ON_Xform saved_model_xform;
    // Save the current model transformation, we will
    // need to restore it later
    vp.GetModelXform( saved_model_xform );
    // Set the model transformation to ours
    vp.SetModelXform( m_xform );
    // Draw all of the objects in our array
    for( i = 0; i < m_objects.Count(); i++ )
    {
      const CRhinoObject* object = m_objects[i];
      if( object == 0 )
        continue;
      vp.SetDrawColor( object->ObjectDrawColor(TRUE) );
      object->Draw( vp );
      if( vp.InterruptDrawing() )
        break;
    }
    // Reset modified viewport members
    vp.SetModelXform( saved_model_xform );
    vp.SetDrawColor( saved_color );
  }

  // Let the base class do its drawing too
  CRhinoGetPoint::DynamicDraw( hdc, vp, pt );
}