Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Just can't get GetPixelInfoPoint to work :-(

    SDK Help
    0
    41
    33.1k
    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 17/06/2014 at 12:27, xxxxxxxx wrote:

      At the risk of posting too much code.
      Here's an entire Tool plugin I wrote a while ago using ViewportSelect() and GetPixelInfoPoint() to select the points of an object. With a range value option.

      //This is an example of using a radius to select points of an object  
      //Once the points are found. The ViewportSelect class is used to select them in the scene  
        
      #include "c4d.h"  
      #include "radSelect.h"  
      #include "c4d_symbols.h"  
        
      #define ID_SCULPTING_TOOL 000000002  //Testing ID ONLY!!!!  
        
      class RadiusSelect : public DescriptionToolData  
      {  
        public:  
        RadiusSelect();  
        virtual ~RadiusSelect();  
        
        private:  
        virtual LONG GetToolPluginId() { return ID_SCULPTING_TOOL; }  
        virtual const String GetResourceSymbol() { return String("radSelect"); }  
        virtual Bool InitTool(BaseDocument *doc, BaseContainer &data, BaseThread *bt);  
        virtual void FreeTool(BaseDocument *doc, BaseContainer &data);  
        virtual void InitDefaultSettings(BaseDocument *doc, BaseContainer &data);  
        virtual Bool GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);  
        virtual Bool MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
          
          
        ViewportSelect *vps;            //USed later on for selecting the points of the object  
        LONG eWinWidth, eWinHeight;     //The editor window's scale values  
        
        //Custom methods to select an object's points if they're within the radius range  
        Bool createVPS(BaseDocument *doc, BaseDraw *bd);  
        void selectRadius(Vector* points, BaseContainer &data, Real mouseX, Real mouseY, Real radius);  
      };  
        
      RadiusSelect::RadiusSelect()  
      {  
        vps = NULL;  
      }  
        
      RadiusSelect::~RadiusSelect()  
      {  
        ViewportSelect::Free(vps);  
      }  
        
      Bool RadiusSelect::InitTool(BaseDocument *pDoc, BaseContainer &data, BaseThread *bt)  
      {  
        if(!DescriptionToolData::InitTool(pDoc, data, bt)) return FALSE;  //Loads the .res file gizmo stuff  
          
        //Since we could launch this tool many times  
        //We will free the ViewportSelect memory used every time it launches as a precaution  
        ViewportSelect::Free(vps);  
        
        return TRUE;  
      }  
        
      void RadiusSelect::FreeTool(BaseDocument *pDoc, BaseContainer &data)  
      {  
        //Free the memory used when the plugin closes  
        ViewportSelect::Free(vps);  
        DescriptionToolData::FreeTool(pDoc,data);  
      }  
        
      void RadiusSelect::InitDefaultSettings(BaseDocument *doc, BaseContainer &data)  
      {  
        data.SetReal(SELECTION_RADIUS, 40.0);  
        DescriptionToolData::InitDefaultSettings(doc, data);  
      }  
        
      Bool RadiusSelect::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)  
      {  
        if (bc.GetId()!=BFM_CURSORINFO_REMOVE)  
        {  
            bc.SetString(RESULT_BUBBLEHELP, "My Sculpt Tool");  //Text shown in the bottom left corner of the C4D UI  
            bc.SetLong(RESULT_CURSOR, MOUSE_PAINTMOVE);  
        }  
        
        return TRUE;  
      }  
        
      Bool RadiusSelect::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)  
      {  
        //This is how to get the pixel values for the editor window (the main scene view window) if needed  
        //LONG left, top, right, bottom;               //The pixel dimensions of the editor view window   
        //bd->GetFrame(&left, &top, &right, &bottom);  //Gets the dimensions in pixels of the editor view window an stores them in the above variables  
          
        //This calls to and executes the custom function that allocates an instance of the ViewportSelect class so we can select object points  
        if (!createVPS(doc, bd)) return FALSE;  
        
        Real mouseX = msg.GetReal(BFM_INPUT_X);    //Get the mouse's X position in the editor view  
        Real mouseY = msg.GetReal(BFM_INPUT_Y);    //Get the mouse's Y position in the editor view      
        Real draggingX;                            //We will use these variables to store the mouse's position values while RMB dragging in the editor view  
        Real draggingY;  
        
        PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();  //The object we're sculpting on  
        Vector *points = obj->GetPointW();                             //Gets all of the point positions in the object  
        
        Real radius = data.GetReal(SELECTION_RADIUS);        //Gets the radius value from the GUI options (how many points we will select)   
          
        //This code block checks if the mouse is being dragged with them RMB held down  
        //If it is being dragged...Then it runs the code to move the points in the object  
        win->MouseDragStart(KEY_MLEFT, mouseX, mouseY, MOUSEDRAGFLAGS_DONTHIDEMOUSE);  //Initialise a mouse dragging loop  
        doc->StartUndo();  
        doc->AddUndo(UNDOTYPE_CHANGE, obj);  
        
        BaseContainer draggingBC;   //Stores the dragging data into this container  
        
        //While we're RMB dragging. Send the position values to the draggingX & draggingY variables  
        while (win->MouseDrag(&draggingX, &draggingY, &draggingBC) == MOUSEDRAGRESULT_CONTINUE)  
        {   
            mouseX += draggingX;    //Constantly update and change the X position values  
            mouseY += draggingY;    //Constantly update and change the Y position values  
        
            //Run the custom function that changes the points of the object  
            selectRadius(points, data, mouseX, mouseY, radius);  
        
            //If we don't redraw the editor we won't see the changes until we let go of the RMB   
            DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);  
        }  
        
        win->MouseDragEnd();  
        obj->Message(MSG_UPDATE);  
        doc->EndUndo();  
        
        DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);  
        SpecialEventAdd(EVMSG_UPDATEHIGHLIGHT);  
        
        return TRUE;  
      }  
        
      //A custom method that allocates a ViewportSelect instance so you can select a point on the active object  
      Bool RadiusSelect::createVPS(BaseDocument* doc, BaseDraw* bd)  
      {  
        //If we don't have the vps (ViewportSelect) instance created..then create it  
        if (!vps)  
        {  
            //Only get the active object's points  
            PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();   
            if(obj)  
            {  
                vps = ViewportSelect::Alloc();  
                LONG left, top, right, bottom;  
                bd->GetFrame(&left,  &top, &right, &bottom);  
                eWinWidth = right - left + 1;  
                eWinHeight = bottom - top + 1;  
                if (!vps->Init(eWinWidth, eWinHeight, bd, obj, Mpoints, TRUE, VIEWPORTSELECTFLAGS_0)) return FALSE;  
            }  
        }  
        
        return TRUE;  
      }  
        
      //A custom method that moves the points based on the mouse position, radius, and vector values  
      void RadiusSelect::selectRadius(Vector *points, BaseContainer &data, Real mouseX, Real mouseY, Real radius)  
      {  
        //The object we are targeting to grab it's points with the mouse  
        PolygonObject *obj = (PolygonObject* ) GetActiveDocument()->GetActiveObject();  
        
        Real radSqr = radius * radius;  
        if (radSqr < 1.0) return;  
        
        
        //This code block sets up the radius around the mouse's current position  
        //x1 is amount of screen pixels to check towards the left of the mouse   
        //x2 is amount of screen pixels to check towards the right of the mouse   
        //y1 is amount of screen pixels to check towards the top of the mouse      
        //y2 is amount of screen pixels to check towards the bottom of the mouse  
        LONG x1 = LMax(0, (LONG)(mouseX - radius));              //Gets the mouseX position - the radius value (but returns 0 if value is less than zero)  
        LONG x2 = LMin(eWinWidth - 1, (LONG)(mouseX + radius));  //Gets the mouseX position + the radius value (but returns the screen width if value is more than the screen width)  
        LONG y1 = LMax(0, (LONG)(mouseY - radius));              //Gets the mouseY position - the radius value (but returns 0 if value is less than zero)  
        LONG y2 = LMin(eWinHeight - 1, (LONG)(mouseY + radius)); //Gets the mouseY position + the radius value (but returns the screen height if value is more than the screen height)  
        
          
        //Loop through the pixels in the screen in a matrix like fashion  
        //By getting the pixels using Rows & Columns using 2 for loops  
        for (LONG i = x1; i <= x2; i++)  
        {  
            for (LONG j = y1; j <= y2; j++)  
            {  
                Real rSqrDist = (i - mouseX)*(i - mouseX) + (j - mouseY)*(j - mouseY);  
                if (rSqrDist > radSqr) continue;  
        
                //Get the point of an object in the scene at this screen pixel location  
                ViewportPixel *pPixel = vps->GetPixelInfoPoint(i, j);  
                while (pPixel)  
                {  
                    //If the point found belongs to our desired target object  
                    if (pPixel->op == obj)  
                    {  
                        //This code will select the points on the object if they're within the radius range  
                        BaseSelect *bs = obj->GetPointS();  
                        bs->Select(pPixel->i);  
                    }  
                    pPixel = pPixel->next;  
                }  
            }  
        }  
        
        obj->Message(MSG_UPDATE);  
      }  
        
      Bool RegisterRadiusSelect()  
      {  
        return RegisterToolPlugin(ID_SCULPTING_TOOL, GeLoadString(IDS_RADSELECT_TOOL), 0, AutoBitmap("myicon.png"), GeLoadString(IDS_RADSELECT_TOOL), gNew RadiusSelect);  
      }
      

      I hope that's not too much code to sift through.

      -ScottA

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

        On 17/06/2014 at 12:53, xxxxxxxx wrote:

        It is not too much, Scott 🙂
        Thank you very much.
        I'm eager to sift through it. But, damn!!! I have to go and have dinner now.
        And today is my wife's birthday.
        I guess I will only be able to deal with this later or tomorrow.

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

          On 17/06/2014 at 15:09, xxxxxxxx wrote:

          Scott, I was able to use your code almost exactly as it is, without changes.
          But, ViewportPixel *pPixel = vps->GetPixelInfoPoint(i, j); always returns NULL 😞

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

            On 17/06/2014 at 15:26, xxxxxxxx wrote:

            That's strange.
            I'm getting the object, and the object's point index#s from it just fine in R13.

                //Loop through the pixels in the screen in a matrix like fashion  
              //By getting the pixels using Rows & Columns using 2 for loops  
              for (LONG i = x1; i <= x2; i++)  
              {  
                  for (LONG j = y1; j <= y2; j++)  
                  {  
                      Real rSqrDist = (i - mouseX)*(i - mouseX) + (j - mouseY)*(j - mouseY);  
                      if (rSqrDist > radSqr) continue;  
              
                      //Get the point of an object in the scene at this screen pixel location  
                      ViewportPixel *pPixel = vps->GetPixelInfoPoint(i, j);  
                      while (pPixel)  
                      {  
                          //If the point found belongs to our desired target object  
                          if (pPixel->op == obj)  
                          {  
                              GePrint(pPixel->op->GetName());    //Prints the name of the object we're selecting points on  
                              GePrint(LongToString(pPixel->i));  //Prints the point's index#  
              
                              //This code will select the points on the object if they're within the radius range  
                              BaseSelect *bs = obj->GetPointS();  
                              bs->Select(pPixel->i);  
                          }  
                          pPixel = pPixel->next;  
                      }  
                  }  
              }
            

            I don't know why it's returning Null for you.
            If you want the plugin to play around with. Tell me where to e-mail it and I'll send it to you.

            -ScottA

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

              On 17/06/2014 at 15:41, xxxxxxxx wrote:

              It is a real mystery 😞
              Well, I'm using R14 but it should work fine anyway.
              If you can, please send it over to: [email protected]
              I'm on a Mac, remember?
              Thank you in advance.

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

                On 17/06/2014 at 16:10, xxxxxxxx wrote:

                Oh yeah. I forgot you're on a Mac.
                Having the actual plugin won't help you any more than the code I posted.

                Have you looked at the "sculpting.cpp" example in the SDK examples?
                That one uses the GetPixelInfoPoint() function in it too.

                -ScottA

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

                  On 17/06/2014 at 16:17, xxxxxxxx wrote:

                  Yes, I looked into it.
                  And using the methods that are used there, I still get Null in the vps->GetPixelInfoPoint(x, y)

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

                    On 17/06/2014 at 18:02, xxxxxxxx wrote:

                    I just can't figure out why is this happening 😞

                      
                    (...)   
                    for (LONG i = x1; i <= x2; i++)   
                    {   
                        for (LONG j = y1; j <= y2; j++)   
                        {   
                            Real rSqrDist = (i - mouseX)*(i - mouseX) + (j - mouseY)*(j - mouseY);   
                            if (rSqrDist > radSqr) continue;   
                                      
                            ViewportPixel *pPixel = vps->GetPixelInfoPoint(i, j);   
                      
                    // the code works fine until here. At this point, pPixel is NULL   
                      
                            while (pPixel)   
                            {   
                                if (pPixel->op == obj)   
                                {   
                             GePrint(LongToString(pPixel->i));   
                                }   
                            pPixel = pPixel->next;   
                            }   
                        }   
                    }   
                    (...)
                    
                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 18/06/2014 at 04:52, xxxxxxxx wrote:

                      I tried it with python and it works fine. I just can't make it work with C++
                      This is driving me crazy!!! 😞

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

                        On 18/06/2014 at 05:49, xxxxxxxx wrote:

                        Howdy,

                        Have you looked at ViewportPixel::GetNearestPoint()?

                        That function may be easier to use because it has a radius parameter:

                        ViewportPixel *vp = vps->GetNearestPoint(op,x,y,rad);
                        

                        Adios,
                        Cactus Dan

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

                          On 18/06/2014 at 06:49, xxxxxxxx wrote:

                          Even with GetNearestPoint I still get vp==NULL 😞

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

                            On 18/06/2014 at 07:46, xxxxxxxx wrote:

                            Howdy,

                            Try this sample code:

                            #include "c4d.h"
                            #include "c4d_symbols.h"
                            #include "lib_collider.h"
                              
                            class TestTool : public ToolData
                            {
                            private:
                            	Real mx, my;
                            	Bool mDrag;
                            	
                            public:
                            	virtual TOOLDRAW Draw(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, BaseDrawHelp* bh, BaseThread* bt, TOOLDRAWFLAGS flags);
                            	virtual Bool MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);
                            };
                              
                            TOOLDRAW TestTool::Draw(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, BaseDrawHelp* bh, BaseThread* bt, TOOLDRAWFLAGS flags)
                            {
                            	BaseObject	*op = doc->GetActiveObject(); if(!op) return TOOLDRAW_0;
                            	if(!(op->IsInstanceOf(Opoint) && ToPoint(op)->GetPointR())) return TOOLDRAW_0;
                            	
                            	Real rad = 10.0;
                            	if(mDrag)
                            	{
                            		bd->SetPen(Vector(0,0,0));
                            		bd->DrawCircle2D(LONG(mx),LONG(my),rad);
                            	}
                              
                            	return TOOLDRAW_HANDLES|TOOLDRAW_AXIS|TOOLDRAW_HIGHLIGHTS;
                            }
                              
                            Bool TestTool::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)
                            {
                            	BaseObject	*op = doc->GetActiveObject(); if(!op) return false;
                            	if(!(op->IsInstanceOf(Opoint) && ToPoint(op)->GetPointR())) return false;
                            		
                            	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;
                            	}
                            	
                            	Real rad = 10.0;
                            	Bool vOnly = true;
                            	
                            	AutoAlloc<ViewportSelect> vps; if(!vps) return false;
                            	
                            	LONG left, top, right, bottom, width, height;
                            	bd->GetFrame(&left, &top, &right, &bottom);
                            	width = right - left + 1;
                            	height = bottom - top + 1;
                            	
                            	vps->Init(width,height,bd,op,Mpoints,vOnly,VIEWPORTSELECTFLAGS_USE_HN|VIEWPORTSELECTFLAGS_USE_DEFORMERS);
                            	vps->SetBrushRadius(rad);
                              
                            	Real dx, dy;
                            	mDrag = false;
                            	BaseContainer bc, device;
                            	win->MouseDragStart(button,mx,my,MOUSEDRAGFLAGS_DONTHIDEMOUSE|MOUSEDRAGFLAGS_NOMOVE);
                            	while (win->MouseDrag(&dx,&dy,&device)==MOUSEDRAGRESULT_CONTINUE)
                            	{
                            		mx+=dx;
                            		my+=dy;
                            		mDrag = true;
                            		LONG x = mx, y = my;
                            		
                            		ViewportPixel *vp = vps->GetNearestPoint(op,x,y,rad);
                            		if(vp)
                            		{
                            			GePrint(LongToString(vp->i));
                            		}
                            		DrawViews(DRAWFLAGS_INDRAG|DRAWFLAGS_NO_REDUCTION|DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);
                            	}
                            	mDrag = false;
                            	EventAdd(EVENT_FORCEREDRAW);
                              
                            	return TRUE;
                            }
                              
                            #define ID_TOOLDATA_TEST		1000007
                              
                            Bool RegisterTestTool(void)
                            {
                            	return RegisterToolPlugin(ID_TOOLDATA_TEST,"Test Tool",0,AutoBitmap("Test.tif"),"Test Tool",gNew TestTool);
                            }
                            

                            Adios,
                            Cactus Dan

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

                              On 18/06/2014 at 08:37, xxxxxxxx wrote:

                              I replaced all my code with your code and added the following:

                              (...)
                              ViewportPixel *vp = vps1->GetNearestPoint(op,x,y,rad);
                              if(vp)
                              {
                                   GePrint(LongToString(vp->i));
                              }
                              else
                              {
                                   GePrint("vp is NULL");
                              }
                              (...)

                              And all I got, as I dragged the cursor was "vp is NULL" in the Console 😞

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

                                On 18/06/2014 at 09:11, xxxxxxxx wrote:

                                Howdy,

                                OK, I added the line:

                                else GePrint("vp is NULL");
                                

                                ... and it only prints that when the mouse is not over a point of the object and within the radius.

                                Adios,
                                Cactus Dan

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

                                  On 18/06/2014 at 09:24, xxxxxxxx wrote:

                                  If the code works in Python. Then It's not a code problem.

                                  The simplest way to check it is to put this in the sculpting.cpp file's while loop: GePrint(pPixel->op->GetName());
                                  If this returns NULL and not the name of the object. Then there's got to be something wrong with your SDK installation.

                                  -ScottA

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

                                    On 18/06/2014 at 09:33, xxxxxxxx wrote:

                                    So, why the hell is it not working for me?!?
                                    Would you guys be willing to check out my code?
                                    It is not much longer than the one posted above by Scott 😉

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

                                      On 18/06/2014 at 09:38, xxxxxxxx wrote:

                                      Howdy,

                                      Hehe, at this point that may be your only option. If you want to keep your code confidential, feel free to pm or email it to one of us.

                                      Adios,
                                      Cactus Dan

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

                                        On 18/06/2014 at 09:38, xxxxxxxx wrote:

                                        Scott, I did what you said and the sculpt tool works fine and prints out the name of the object.

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

                                          On 18/06/2014 at 09:44, xxxxxxxx wrote:

                                          Well, I will send it through pm just because I don't want to show my lame code to everyone 😉
                                          Thank you very much in advance.

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

                                            On 18/06/2014 at 09:50, xxxxxxxx wrote:

                                            I just sent you a PM with my code, Dan.
                                            I will only send it to Scott if he says it is OK to do so.
                                            Thank you very much in advance to both of you.

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post