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 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
          • H
            Helper
            last edited by

            On 18/06/2014 at 10:29, xxxxxxxx wrote:

            If Dan's willing to help you out. There's no need to send it to me Rui.
            He can probably help you better than I can.
            Plus, he's a Mac user. So you can send files to each other. And I can't do that.

            -ScottA

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

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

              Thank you very much for the help, anyway, Scott 🙂
              I guess I will be needing more help in the near future, now that I jumped on the C++ boat.
              I can compile for Mac and Windows and that is great. But I'm still a newbie.

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

                On 18/06/2014 at 10:53, xxxxxxxx wrote:

                Howdy,

                Well, I added your "CheckRadius" function to the test code that I posted, and it always prints "pPixel is NULL" the same as you're getting. So that function looks like it is the culprit.

                But if I change the code in that function to:

                LONG x = mouseX;
                LONG y = mouseY;
                ViewportPixel *pPixel = vps->GetNearestPoint(current_obj,x,y,radius);
                if(pPixel) GePrint(LongToString(pPixel->i));
                else GePrint("pPixel is NULL");
                

                ... then it works.

                What is the purpose of the code in CheckRadius()? I mean why the nested for() loops?

                Edit:
                I can see using the nested for() loops in the sculpting tool example in the sdk project, because that tool would need to affect the surrounding points along with the point under the mouse, therefore the use of:

                pPixel = pPixel->next;
                

                ... but for a painting tool, it just seems like the GetNearestPoint() function would be the easier.

                Adios,
                Cactus Dan

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

                  On 18/06/2014 at 12:41, xxxxxxxx wrote:

                  Well, it is a painting tool that should paint ALL points inside the radius.
                  But since the ViewportPixel structure is a linked list, maybe the GetNearestPoint returns a linked list of all points that are withing the radius.
                  I will give it a try 🙂
                  Thank you, Dan.

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

                    On 18/06/2014 at 12:54, xxxxxxxx wrote:

                    Damn!!
                    Now my CheckRadius function is just:

                      
                    void cPolyPaintTool::CheckRadius(BaseDocument* doc, BaseContainer &data;, Real mouseX, Real mouseY, Real radius)   
                    {   
                    LONG x = _mouseX;   
                    LONG y = _mouseY;   
                    LONG rad = radius;   
                            
                    ViewportPixel* pPixel = vps->GetNearestPoint(current_obj, x, y,rad,FALSE,NULL,0);   
                                      
                    if (pPixel) GePrint(LongToString(pPixel->i));   
                    else   
                         GePrint("pPixel is NULL");   
                    }   
                    

                    And I still only get "pPixel is NULL". It never printed an index.

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

                      On 18/06/2014 at 13:56, xxxxxxxx wrote:

                      Howdy,

                      Maybe it is working?

                      Here's a test I did. I added a breakpoint within the while loop in your original CheckRadius() function code, and ran it in the Debugger. The debugger did break at that point, which means that at least one pass through the loop did return a valid pointer to the ViewportPixel. It's just that there were so many other passes that return NULL, that I missed it in the console.

                      Here's a screen capture video showing it:
                      http://www.cactus3d.com/BreakPoint.mov

                      You can see in the video that 1 pass did print "1" to the console which is the point's index I clicked on in the viewport.

                      Adios,
                      Cactus Dan

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

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

                        So, why doesn't it return lots of indexes when I search for the points inside the nested loops?
                        Because I'm "painting" on top of a very dense mesh.

                        p.s. I don't know how to run a plugin in the Debugger 😞

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

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

                          Howdy,

                          Well, remember that the console has a line limit, so when it goes over that limit, it starts truncating lines from the beginning.

                          Have you tried commenting out the line to print when it's NULL, and see if anything is printed to the console?

                          Adios,
                          Cactus Dan

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

                            On 18/06/2014 at 14:15, xxxxxxxx wrote:

                            Yes, I did. And nothing gets printed 😞

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

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

                              Howdy,

                              When it prints nothing are simply clicking on a point or are you dragging the mouse over the point?

                              Adios,
                              Cactus Dan

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

                                On 18/06/2014 at 15:23, xxxxxxxx wrote:

                                It prints nothing, no matter if I click or drag the mouse over the point(s).

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

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

                                  Howdy,

                                  Hmmmm, the code you sent me seems to be working. I commented out all the checks for the tag, and made it a ToolData instead of a DescriptionToolData, since I didn't have the resource files. But I've only tested it in R12 (that's where I do all my initial development) with a simple cube and it seems to be fine.

                                  Adios,
                                  Cactus Dan

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

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

                                    Weird...
                                    If I change tools (for example, if I choose the Scale tool, and then my plugin tool) it works!!

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

                                      On 18/06/2014 at 16:56, xxxxxxxx wrote:

                                      Oh man.
                                      I was going to mention this earlier. But I didn't think it would trip you up.
                                      If you look at the code example I posted. And the code in the sculpting.cpp file. You'll notice that the sculpting.cpp file has an "Update" function in it. Plus a bunch of OpenGL stuff and timers code in it.

                                      I removed all that junk from my example. Because It was very ugly code. And very convoluted.
                                      But what that means is that if you want to use the tool on a different object. Then you have to select one of the other tool modes (move, rotate, scale). And then re-select your tool so the new object gets initialized to work with the different object.
                                      It's one of those things that I was meaning to try and fix some day.
                                      The code in the sculpting example that handles this is a complete mess.

                                      Since it works fine on the first selected object. I didn't think it would cause a problem for you.
                                      But if that's the reason you're having problems. I should have mentioned it sooner. !Embarrassed[URL-REMOVED]

                                      -ScottA


                                      [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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

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

                                        So, I guess I will have to implement the Update function that is in the sculpt tool, right?

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

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

                                          If your tool is working properly after you switch to another mode, then select the tool again...Then yes. You'll need to write something to handle that scenario. Like they did in the SDK sculpting example.
                                          I personally never got that far with my plugin.

                                          The code they used in the SDK for this is terribly ugly. And I'm sure there's a cleaner, more elegant way to write it without all of those custom methods, timers, and junk.

                                          -ScottA

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

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

                                            I found another Tool plugin that I forgot that I wrote a while ago.
                                            This one does not select the points. It moves them. Just like the SDK sculpting tool plugin.
                                            The reason why I made this one is because the SDK example was too messy and confusing for me to understand.

                                            This one does not appear to need you to selected other tool modes when working another object.
                                            I think the "lDirty" stuff throughout the code handles that. It's been a long time since I wrote it and I can't remember.
                                            The other example doesn't have this code in it.

                                            #include "c4d.h"  
                                            #include "sculptingtool.h"  
                                            #include "c4d_symbols.h"  
                                              
                                            #define ID_SCULPTING_TOOL 000000001  //Testing ID ONLY!!!!  
                                              
                                            class MySculptingTool : public DescriptionToolData  
                                            {  
                                              public:  
                                              MySculptingTool();  
                                              virtual ~MySculptingTool();  
                                              
                                              private:  
                                              virtual LONG GetToolPluginId() { return ID_SCULPTING_TOOL; }  
                                              virtual const String GetResourceSymbol() { return String("sculptingtool"); }  
                                              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);  
                                              
                                              //Custom methods to check if the mouse is within the editor view and a method that actually moves them  
                                              Bool ValidateViewport(BaseDocument *doc, BaseDraw *bd);  
                                              void UpdateObject(Vector* points, BaseContainer &data, Real mouseX, Real mouseY, Real radius, const Vector &vDelta);  
                                              
                                              //Variables used for testing if the mouse is within the editor view window  
                                              ViewportSelect *m_pViewportSelect;  
                                              Bool m_bViewportValid;  
                                              BaseDraw *m_pLastBaseDraw;  
                                              LONG m_lLastWidth, m_lLastHeight;  
                                              LONG m_lLastDirty;  
                                              LONG m_lLastEditorCameraDirty;  
                                            };  
                                              
                                            MySculptingTool::MySculptingTool()  
                                            {  
                                              m_pViewportSelect = NULL;  
                                              m_pLastBaseDraw = NULL;  
                                              m_bViewportValid = FALSE;  
                                              m_lLastDirty = 0;  
                                            }  
                                              
                                            MySculptingTool::~MySculptingTool()  
                                            {  
                                              ViewportSelect::Free(m_pViewportSelect);  
                                            }  
                                              
                                            Bool MySculptingTool::InitTool(BaseDocument *pDoc, BaseContainer &data, BaseThread *bt)  
                                            {  
                                              if(!DescriptionToolData::InitTool(pDoc, data, bt)) return FALSE;  
                                              
                                              m_bViewportValid = FALSE;  
                                              m_pLastBaseDraw = NULL;  
                                              ViewportSelect::Free(m_pViewportSelect);  
                                              m_lLastWidth = m_lLastHeight = -1;  
                                              m_lLastDirty = 0;  
                                              
                                              return TRUE;  
                                            }  
                                              
                                            void MySculptingTool::FreeTool(BaseDocument *pDoc, BaseContainer &data)  
                                            {  
                                              m_lLastDirty = 0;  
                                              ViewportSelect::Free(m_pViewportSelect);  
                                              DescriptionToolData::FreeTool(pDoc,data);  
                                            }  
                                              
                                            void MySculptingTool::InitDefaultSettings(BaseDocument *doc, BaseContainer &data)  
                                            {  
                                              data.SetReal(SCULPTING_RADIUS, 40.0);  
                                              data.SetVector(SCULPTING_VECTOR, Vector(0.0, 2.0, 0.0));  
                                              DescriptionToolData::InitDefaultSettings(doc, data);  
                                            }  
                                              
                                            Bool MySculptingTool::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 MySculptingTool::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 lLeft, lTop, lRight, lBottom;               //The pixel dimensions of the editor view window   
                                              //bd->GetFrame(&lLeft, &lTop, &lRight, &lBottom);  //Gets the dimensions in pixels of the editor view window an stores them in the above variables  
                                                
                                              //This calls to this custom function to check if the mouse is within the editor window or not  
                                              //If the mouse is outside of the editor window..We bail out and don't go any farther  
                                              if (!ValidateViewport(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(SCULPTING_RADIUS);        //Gets the radious value from the GUI options (how many points we will move)  
                                              Vector vMove = data.GetVector(SCULPTING_VECTOR);     //Gets the vector value from the GUI options (the direction & amount we'll move the points)  
                                                
                                              //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  
                                                  UpdateObject(points, data, mouseX, mouseY, radius, vMove);  
                                              
                                                  //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 checks if the mouse is within the editor window or not  
                                            Bool MySculptingTool::ValidateViewport(BaseDocument* doc, BaseDraw* bd)  
                                            {  
                                              LONG lLeft, lTop, lRight, lBottom;  
                                              LONG lDirty;  
                                              BaseObject *pSelected;  
                                              PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();  
                                              
                                              bd->GetFrame(&lLeft, &lTop, &lRight, &lBottom);  
                                              
                                              lRight = lRight - lLeft + 1;  
                                              lBottom = lBottom - lTop + 1;  
                                              
                                              BaseObject *pCam = bd->GetSceneCamera(doc) ? bd->GetSceneCamera(doc) : bd->GetEditorCamera();  
                                              
                                              if (!doc->IsCacheBuilt()) return FALSE;  
                                              
                                              pSelected = doc->GetActiveObject();  
                                              if(pSelected && pSelected->IsInstanceOf(Opolygon))  
                                              {  
                                                  lDirty = pSelected->GetDirty(DIRTYFLAGS_DATA | DIRTYFLAGS_MATRIX);  
                                              }  
                                              else  
                                              {  
                                                  pSelected = NULL;  
                                                  lDirty = 0;  
                                              }  
                                              
                                              if (bd != m_pLastBaseDraw) m_bViewportValid = FALSE;  
                                              if (m_bViewportValid && (lRight != m_lLastWidth || lBottom != m_lLastHeight)) m_bViewportValid = FALSE;  
                                              if (m_bViewportValid && !(pSelected == obj && lDirty == m_lLastDirty)) m_bViewportValid = FALSE;  
                                              if (m_bViewportValid && m_lLastEditorCameraDirty != pCam->GetDirty(DIRTYFLAGS_MATRIX | DIRTYFLAGS_DATA)) m_bViewportValid = FALSE;  
                                              if (!m_bViewportValid) ViewportSelect::Free(m_pViewportSelect);  
                                              
                                              if (!m_pViewportSelect)  
                                              {  
                                                  obj = (PolygonObject* )pSelected;  
                                                  m_lLastDirty = lDirty;  
                                                  m_lLastWidth = lRight;  
                                                  m_lLastHeight = lBottom;  
                                                  m_pLastBaseDraw = bd;  
                                                  m_pViewportSelect = ViewportSelect::Alloc();  
                                                  m_bViewportValid = TRUE;   
                                                  m_lLastEditorCameraDirty = pCam->GetDirty(DIRTYFLAGS_DATA | DIRTYFLAGS_MATRIX);  
                                              
                                                  if (!m_pViewportSelect) return FALSE;  
                                                  if (obj)  
                                                  {  
                                                      if (!m_pViewportSelect->Init(m_lLastWidth, m_lLastHeight, bd, obj, Mpoints, FALSE, VIEWPORTSELECTFLAGS_0)) return FALSE;  
                                                  }  
                                              }  
                                              
                                              return TRUE;  
                                            }  
                                              
                                            //A custom method to get the square of a decimal  
                                            Real sqr(Real r)  
                                            {  
                                              return r * r;  
                                            }  
                                              
                                            //A custom method that moves the points based on the mouse position, radius, and vector values  
                                            void MySculptingTool::UpdateObject(Vector *points, BaseContainer &data, Real mouseX, Real mouseY, Real radius, const Vector &vDelta)  
                                            {  
                                              PolygonObject *obj = (PolygonObject* ) GetActiveDocument()->GetActiveObject();  //The object we're sculpting on  
                                              
                                              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(m_lLastWidth - 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(m_lLastHeight - 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 screen's pixes in a matrix like fashion  
                                              //By getting the screen pixels using Rows & Columns using 2 for loops  
                                              for (LONG x = x1; x <= x2; x++)  
                                              {  
                                                  for (LONG y = y1; y <= y2; y++)  
                                                  {  
                                                      Real rSqrDist = sqr(x - mouseX) + sqr(y - mouseY);  
                                                      if (rSqrDist > radSqr) continue;  
                                              
                                                      ViewportPixel *pPixel = m_pViewportSelect->GetPixelInfoPoint(x, y);  
                                                      while (pPixel)  
                                                      {  
                                                          if (pPixel->op == obj)  
                                                          {  
                                                              //Get the points on the object that matches the editor views pixel values(the points under the mouse)  
                                                              //Smoothstep creates a smooth falloff effect and moves the point in a smooth motion  
                                                              points[pPixel->i] += vDelta * Smoothstep(0.0, 1.0, (1.0 - rSqrDist / radSqr));  
                                              
                                                              //This code will select the points if desired  
                                                              Bool selpnts = data.GetReal(SELECT_POINTS);  
                                                              if(selpnts)  
                                                              {  
                                                                  BaseSelect *bs = obj->GetPointS();  
                                                                  bs->Select(pPixel->i);  
                                                              }  
                                                          }  
                                                          pPixel = pPixel->next;  
                                                      }  
                                                  }  
                                              }  
                                              
                                              obj->Message(MSG_UPDATE);  
                                            }  
                                              
                                            Bool RegisterMySculptingTool()  
                                            {  
                                              return RegisterToolPlugin(ID_SCULPTING_TOOL, GeLoadString(IDS_SCULPTING_TOOL), 0, AutoBitmap("myicon.png"), GeLoadString(IDS_SCULPTING_TOOL), gNew MySculptingTool);  
                                            }
                                            

                                            -ScottA

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