Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Draw circle at cursor on object surface?

    SDK Help
    0
    5
    611
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 15/06/2013 at 02:07, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R13+ 
      Platform:   Windows  ;   Mac OSX  ; 
      Language(s) :     C++  ;

      ---------
      What is needed is some way to 'project' (in Draw() for a Tool plugin) a circle of a given radius from the screen onto the surface of an object (that results in a polygonal mesh) using the cursor as center.  The circle needs to be oriented on the plane perpendicular to the surface normal at that point.  This is probably very much like UV mapping but with the limitations of BaseDraw, it may require converting UV coordinates to pixels somehow (?).  I will do some research but some direction or code would be helpful in the meantime.

      One possibility might be to shoot rays in the direction of the normal towards the surface in a sparse circular pattern and do line seqments from point to point over the intersections that are visible to the camera.  A bit of work but the results should be perfect.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 15/06/2013 at 02:39, xxxxxxxx wrote:

        I would go for the utils.ViewportSelect plus BaseView.ProjectPointOnLine() and ProjectPointOnPlane().

        Happy rendering,
        Ferdinand

        edit : ok that was maybe a bit too short - what i meant was, construct your circle in camera space
        around your desired center and then project its points on the surface(s). with a z-depth high 
        enough you won't have to worry so much about a matching subdiv, as you will simply draw over
        the geometry.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 15/06/2013 at 02:51, xxxxxxxx wrote:

          That would work if the circle were being directly projected from the screen (camera).  But it going to be projected to the plane perpendicular to the surface normal under the cursor.

          I've also determined that line segments (LineStrip()) may not work if there are discontinuities (surface not seen by camera or the circle point misses the mesh entirely).

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 15/06/2013 at 03:12, xxxxxxxx wrote:

            Ah ok,

            converting the coords for ViewportSelect forth and back would be indeed a bit clunky.
            An alternative root would be the new snapping core class. i guess it is easier to use 
            than the GeRayCollider were you have usually to worry about the hit sides and so on,
            but i am not sure about the snapping core performance.

            happy rendering,
            ferdinand

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 15/06/2013 at 06:47, xxxxxxxx wrote:

              So far so good except for one thing.  Transforming the calculated circle points from a local Z-plane ( Vector(radius+Cos(angle), radius*Sin(angle), 0.0)) to the local plane representing the negative surface normal (translated away from the surface for ray collision) is resulting in elliptical circles.  This is either a skewing in the matrix or the rotation (axis-angle) isn't correct.  Uncertain which is the cause.  All vectors are in local space for the object.

              Here is my code (and some alternatives which show the same issue) :

              Vector    ray_dir =            !(res.f_normal);  
                
              // - Move the ray system far away from the surface, orient it and put it into object space  
              // Rodrigues method  
              Vector    pnormal =            Vector(0.0,0.0,1.0);  
              // - invert normal to point at surface not away from it  
              ray_dir =                    -ray_dir;  
              Vector axis =                !(pnormal%ray_dir);  
              Matrix    pmat;  
              pmat.v1 =    Vector(0.0, -axis.z, axis.y);  
              pmat.v2 =    Vector(axis.z, 0.0, -axis.x);  
              pmat.v3 =    Vector(-axis.y, axis.x, 0.0);  
              Real    angle =                ACos(pnormal*ray_dir);  
              pmat =        unitMatrix + Sin(angle)*pmat + (1.0-Cos(angle))*pmat*pmat;  
              // Quaternion method  
              /*   
              Quaternion    q;  
              q.SetAxis(!(pnormal%ray_dir), ACos(pnormal*ray_dir));  
              Matrix    pmat =                q.GetMatrix();  
              */  
              // Axis-Angle method  
              //Matrix    pmat =                RotAxisToMatrix(!(pnormal%ray_dir), ACos(pnormal*ray_dir));  
              //pmat.Normalize();  
              pmat.off =                    res.hitpos+(ray_dir*-50000.0);  
              Real    radius =            (Real)data.GetLong(TOOLHDRLS_RADIUS);  
              Real    dangle =            0.1745329251994329;  
              Vector    fp;  
              Bool    drawfp =            FALSE;  
              bd->LineStripBegin();  
              // - First point  
              pnormal =                    pmat * Vector(radius*Cos(0.0), radius*Sin(0.0), 0.0);  
              if (m_pDrawCollider->Intersect(pnormal, ray_dir, 100000.0) && m_pDrawCollider->GetNearestIntersection(&res))  
              {  
                bd->LineStrip(res.hitpos, hicolor, NOCLIP_D|NOCLIP_Z);  
                fp =        res.hitpos;  
                drawfp =    TRUE;  
              }  
              for (LONG i = 1L; i != 36L; ++i, dangle += 0.1745329251994329)  
              {  
                pnormal =        pmat * Vector(radius*Cos(dangle), radius*Sin(dangle), 0.0);  
                if (m_pDrawCollider->Intersect(pnormal, ray_dir, 100000.0) && m_pDrawCollider->GetNearestIntersection(&res))  
                    bd->LineStrip(res.hitpos, hicolor, NOCLIP_D|NOCLIP_Z);  
              }  
              // - Back to first point  
              if (drawfp)                    bd->LineStrip(fp, hicolor, NOCLIP_D|NOCLIP_Z);  
              bd->LineStripEnd();  
              
              1 Reply Last reply Reply Quote 0
              • First post
                Last post