Tool plugin selecting points?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 10:57, xxxxxxxx wrote:

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

    ---------
            Howdy,

    I've made a tool to go with a tag that will select points on an object. It works ok so far except that I'm not sure how to get it to not select the points on the back side of the object that can't be seen from the point of view of the camera. I did a search here and in the archive but couldn't come up with any answers.

    I tried this but it doesn't seem to be working:

    while (win->MouseDrag(&dx;,&dy;,&device;)==MOUSEDRAG_CONTINUE)
         {
              mx+=dx;
              my+=dy;
              mDrag = TRUE;
              for(i=0; i<ptCount; i++)
              {
                   if(bd->TestPointZ(bd->WC(opActive->GetMg() * padr{i})))
                   {
                        opt = bd->WS(opActive->GetMg() * padr{i});
                        opt.z = 0.0;
                        mpt.x = mx;
                        mpt.y = my;
                        mpt.z = 0.0;
                        if(Len(opt-mpt) < rad) bs->Select({i});
                   }
              }
              DrawViews(DA_ONLY_ACTIVE_VIEW|DA_NO_THREAD|DA_NO_ANIMATION);
         }

    I don't know if that is the correct function to use but it was the only thing I could find in the SDK that looked like the right function.

    How do I test to see if the point is on the back side of the object?

    Adios,
    Cactus Dan

    P.S. the regular brackets for the arrays are supposed to be square brackets, but it looks like that's forum code for italic type. I had to edit the post 5 times. :(



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 12:33, xxxxxxxx wrote:

    Easiest approach is to do a 'backfacing polygon' check using the camera location as the reference. This is usually done after projecting the polygon into 2D. If the winding order of the polygon's points are opposite forwardfacing polygons, its points can safely be ignored.

    As for the italic thing, I usually just edit my source in NotePad or something to change the index from 'i' to something else (not 'b' for bold, of course).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 16:05, xxxxxxxx wrote:

    Howdy,

    That sounds pretty good, but what if the polygons surrounding the point are facing front but theres another part of the object blocking the point from view. I want to have the same option as the selection tool "Only Select Visible Elements".

    A point could be facing front but could be also hidden by something in front of it. I at first considered using the BadkfaceCulling() function from BaseView, but realized that the above described situation would cause that not to work.

    Here's what the SDK says:
    Bool TestPointZ(const Vector& p)

    Returns TRUE if the point is visible in the view according to the current projection. The point must be in camera space.

    Return
    Bool

    TRUE if the point is visible, otherwise FALSE.

    Parameters
    const Vector& p

    Point.

    But that doesn't seem to work. How else could I detect that the point is hidden from view?

    Adios,
    Cactus Dan



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 17:35, xxxxxxxx wrote:

    Well, yes. That won't work. That is 'Frustrum Clipping' of points outside of the camera's view volume (not whether or not the point is 'obscured' within the view).

    For what you're trying to do, you'll need to do both backface culling (points on polygons facing away from the camera) and, worse, hidden surface determination (points on polygons obscured by other polygons).

    I don't know what facilities are available for these tasks in the SDK, but I'll have a gander and see! :)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 17:53, xxxxxxxx wrote:

    Howdy,

    I did another search and found this thread about the same thing:
    Visible Point Question
    It seems that I need to look into the GeRayCollider class.

    Adios,
    Cactus Dan



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/10/2005 at 18:00, xxxxxxxx wrote:

    That looks like the best bet. I was going to suggest VolumeData::TraceGeometry() which uses a Ray for hit determination - but it looked more for raytracing than general 3D work.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/10/2005 at 10:01, xxxxxxxx wrote:

    Howdy,

    OK, I'm a little confused working with the GeRayCollider. I've got it working but it's only working when the object's matrix is the identity matrix (object at world 0,0,0).

    Here is the code:

    Bool TestTool::MouseInput(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg;)  
    {  
         BaseObject     *opActive = doc->GetActiveObject();  
         if (!opActive->IsInstanceOf(Opoint)) return TRUE;  
      
         Vector     rayDir, rayPt, rayEnd, rayStart, opt, mpt, *padr = ToPoint(opActive)->GetPoint();  
         LONG     index, ptCount = ToPoint(opActive)->GetPointCount();  
      
         mx = msg.GetReal(BFM_INPUT_X);  
         my = msg.GetReal(BFM_INPUT_Y);  
         LONG button;  
           
         switch (msg.GetLong(BFM_INPUT_CHANNEL))  
         {  
              case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
              case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
              default: return TRUE;  
         }  
           
         AutoAlloc<GeRayCollider> rc;  
         if (!rc) return FALSE;  
         rc->Init(opActive, TRUE);  
      
         Real                    dx, dy, rad=10.0;  
         mDrag = FALSE;  
         BaseContainer bc, device;  
         BaseSelect *bs = ToPoint(opActive)->GetPointS(); if (!bs) return TRUE;  
         win->MouseDragStart(button,mx,my,MOUSEDRAG_DONTHIDEMOUSE|MOUSEDRAG_NOMOVE);  
         while (win->MouseDrag(&dx;,&dy;,&device;)==MOUSEDRAG_CONTINUE)  
         {  
              mx+=dx;  
              my+=dy;  
              mDrag = TRUE;  
              for(index=0; index<ptCount; index++)  
              {  
                   opt = bd->WS(opActive->GetMg() * padr[index]);  
                   opt.z = 0.0;  
                   mpt.x = mx;  
                   mpt.y = my;  
                   mpt.z = 0.0;  
                   if(Len(opt - mpt) < rad)  
                   {  
                        rayEnd = bd->SW(Vector(mx,my,0));  
                        rayStart = bd->SW(Vector(mx,my,10000.0));  
                        rayDir = (opActive->GetMg()) * (rayEnd - rayStart);  
                        rayPt = (opActive->GetMg() * padr[index]) + !rayDir*0.1;  
                        if(!rc->Intersect(rayPt, rayDir, 10000.0))  
                        {  
                              bs->Select(index);  
                        }  
                        else GePrint("Intersections = "+LongToString(rc->GetIntersectionCount()));  
                   }  
              }  
              DrawViews(DA_ONLY_ACTIVE_VIEW|DA_NO_THREAD|DA_NO_ANIMATION);  
         }  
         mDrag = FALSE;  
         DrawViews(DA_ONLY_ACTIVE_VIEW|DA_NO_THREAD|DA_NO_ANIMATION);  
      
         return TRUE;  
    }
    

    The SDK docs say that rayPt and the rayDir need to be in "object coordinates" so I also tried these lines:

      
                        rayDir = (!opActive->GetMg()) * (rayEnd - rayStart);  
                        rayPt = (!opActive->GetMg() * padr[index]) + !rayDir*0.1;  
    

    But, that doesn't make any difference. It still only works if the object is at the origin. How do I ensure that the rayPt and rayDir are in "object coordinates"?

    Adios,
    Cactus Dan



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 10/10/2005 at 07:12, xxxxxxxx wrote:

    Howdy,

    Well, all I can say is DOH! :(

    This is the way to do it:

      
                        rayDir = (!opActive->GetMg()) * (rayEnd - rayStart);  
                        rayPt = padr[index]) + !rayDir*0.1;  
    

    The points array is already in "object coordinates" so it doesn't need converting.

    Adios,
    Cactus Dan


Log in to reply