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

    Null object dimensions

    SDK Help
    0
    25
    13.2k
    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

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

      On 12/09/2012 at 03:13, xxxxxxxx wrote:

      You need to bring the min max vectors of each object's bounding into global space. This can be done by multiplying with the global matrix of the object.

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

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

        On 12/09/2012 at 07:18, xxxxxxxx wrote:

        Hello Matthias,

        thanks for your answer. Hm.. I don't really get it. With the bbmin and bbmax I get two points that
        are "spanning" the bounding box of the object. But when those are rotated, other points of the
        box might be more outside of it. Hard to express. Maybe this video explains it a little more.

        I have tested this just for a single box for now. This is the code I used.

        def bounding_box(op) :  
          mg = op.GetMg()  
          bb = op.GetRad() * mg  
          mp = op.GetMp()  * mg  
          bbmin , bbmax = (mp - bb), (mp + bb)  
          
          mp = (bbmin + bbmax) * 0.5  
          bb = bbmax - mp  
          return bb, mp
        

        Thanks,
        Niklas

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

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

          On 12/09/2012 at 07:39, xxxxxxxx wrote:

          Hi,

          here a function I wrote.
          Note that it is not recursive - if you have a Null as a child it won't work properly.
          What it does is go through every points of every object in the group and save the min and max in global coordinates.

            
          # get min and max points of a group in global coordinates  
          def getMinAndMaxPoints(nullObj) :  
            if (nullObj.GetType() != c4d.Onull) :   
                #no group  
                children = [nullObj]  
            else:      
                children = nullObj.GetChildren()  
                  
            groupPos = c4d.Vector(0)  
            groupSize = Vector(0)  
            groupMinPoint = Vector(0)  
            groupMaxPoint = Vector(0)  
              
            start = True  
            for child in children:  
                mat = child.GetMg()  
                globalPos = mat.off  
                points =  child.GetAllPoints()  
              
                for point in points:  
                      
                    #print(point + globalPos)  
                    point = point + globalPos  
                    if start == True:      
                        start = False  
                        groupMinPoint = Vector(point)  
                        groupMaxPoint = Vector(point)  
                    else:  
                        if groupMinPoint.x > point.x:  
                            groupMinPoint.x = point.x  
                        if groupMinPoint.y > point.y:  
                            groupMinPoint.y = point.y  
                        if groupMinPoint.z > point.z:  
                            groupMinPoint.z = point.z  
                              
                        if groupMaxPoint.x < point.x:  
                            groupMaxPoint.x = point.x  
                        if groupMaxPoint.y < point.y:  
                            groupMaxPoint.y = point.y  
                        if groupMaxPoint.z < point.z:  
                            groupMaxPoint.z = point.z  
                    #end else  
                #end for points  
            #end for child  
              
            dico = dict()  
            dico["max"] = groupMaxPoint  
            dico["min"] = groupMinPoint  
            return dico  
          

          Alex

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

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

            On 12/09/2012 at 09:18, xxxxxxxx wrote:

            @Al3D: Thanks for your code. But this comes with the huge overhead of iterating over each point of
            each object. GetRad() and GetMp() call ObjectData::GetDimension() which does not necessarily iterate
            over each point in the mesh. On a cube for example, for GetRad(), it would just return the half of its
            size (PRIM_LEN_CUBE) instead of iterating over each point it has generated. Also, when using your
            technique, you could easily hit generator objects.

            I'm so sure there is a better technique, but the only one that comes into my mind is to convert the
            bounding-box retrieved by GetRad() and GetMp() into an 8 point cube, multiply each point with the
            matrix and then check each point. Is there a better way to do it?

            Thanks,
            Niklas

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

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

              On 12/09/2012 at 11:09, xxxxxxxx wrote:

              csto objs(hierarchy) -> join()   🙂

              Cheers
              Lennart

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

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

                On 12/09/2012 at 12:03, xxxxxxxx wrote:

                @tca: Do you mean for converting the generators? 🙂
                Well, I actually don't like the idea of using this method at all. In my current project I need to know the
                BB size in a Tag. This kinda "brute-force" computation would be done every time the tag was
                executed. I could live with that if it would be once or so :X

                -Nik

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

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

                  On 12/09/2012 at 13:27, xxxxxxxx wrote:

                  The computation actually is very negligible up to rather decent setups.
                  One trick is to strip all tags on the returned csto/Cached hierarchy but
                  variable tags (the invisibles, points etc) before running the join command.
                  The other to run/store some base check data, like hierarchy count, sum
                  of vectors or whatever i.e. as well as compare time.

                  Just an idea anyhow, that I use at times anyway 🙂

                  Cheers
                  Lennart

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

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

                    On 13/09/2012 at 06:20, xxxxxxxx wrote:

                    Hey guys,

                    I created a AABBox class for another thread, but expanded it to allow you to add additional objects (cumulative bounding box).  It's in C++, but you're welcome to use/convert it if it's any use...

                      
                    //==================================================================================  
                    // AABBox Class - An implementation of an "Axis Aligned Bounding Box" class  
                    //  
                    // This implementation actually builds a OBB (Oriented Bounding Box) to use as the  
                    // source for generating the AABB.  
                    //  
                    // As implemented, if the object is an instance of a PointObject, it uses the  
                    // (Global-space) points of the object as the OBB.  
                    //  
                    // If it's not a PointObject, it generates a BBox (8-point cube) out of the min/max  
                    // extents of the object (again in Global-space) to use as the OBB.  
                    //  
                    // The class also has provisions for generating a bounding box for a combination of  
                    // multiple objects, as well as a simple collision-detection routine.  
                    //==================================================================================  
                    class AABBox  
                    {  
                    private:  
                      Vector    m_bbMin;  
                      Vector    m_bbMax;  
                      Bool    m_init;  
                      void GetAABBox(BaseObject *op, Vector *pMin, Vector *pMax);  
                      
                    public:  
                      Vector GetMin(void)                        { return m_bbMin; }  
                      Vector GetMax(void)                        { return m_bbMax; }  
                      Bool CollidesWith(BaseObject *op);  
                      void AddObject(BaseObject *op);  
                      void Init(BaseObject *op = NULL);  
                      AABBox(BaseObject *op);  
                      AABBox(void) {    m_init = false; }  
                      ~AABBox(void) {}  
                    };  
                      
                    AABBox::AABBox(BaseObject *op)  
                    {  
                      this->Init(op);  
                    }  
                      
                    void AABBox::Init(BaseObject *op)  
                    {  
                      m_init = false;  
                      m_bbMin = Vector();  
                      m_bbMax = Vector();  
                      if( !op )    return;  
                      
                      this->GetAABBox(op, &m_bbMin, &m_bbMax);  
                      
                      m_init = true;  
                    }  
                      
                    void AABBox::AddObject(BaseObject *op)  
                    {  
                      if( !op )    return;  
                      
                      if( !m_init )  
                      {  
                          this->Init(op);  
                      }  
                      else  
                      {  
                          // first store the old values...  
                          MinMax mm;  
                          mm.Init(m_bbMin);  
                          mm.AddPoint(m_bbMax);  
                      
                          // then add new object...  
                          this->GetAABBox(op, &m_bbMin, &m_bbMax);  
                          mm.AddPoint(m_bbMin);  
                          mm.AddPoint(m_bbMax);  
                      
                          // and determine new extents...  
                          m_bbMin = mm.GetMin();  
                          m_bbMax = mm.GetMax();  
                      }  
                    }  
                      
                    void AABBox::GetAABBox(BaseObject *op, Vector *pMin, Vector *pMax)  
                    {  
                      Matrix opgm = op->GetMgn();  
                      MinMax mm;  
                      
                      //--------------------------------------------------------------------------------------------  
                      // With this implementation, if the BaseObject being passed in is an instance of a PointObject,  
                      // then the OBB will be built from the actual Global-space points... this take longer if there  
                      // are more than 8 points, but gives a tighter fitting AABBox.  If this is too slow, you can  
                      // get rid of this top part and just always do 8 points, below.  
                      //  
                      // to see the difference in using the actual points and the 8 point box, see the image on the  
                      // second page of this article: http://www.gamasutra.com/view/feature/3426/when_two_hearts_collide_.php  
                      //--------------------------------------------------------------------------------------------  
                      if( op->IsInstanceOf(Opoint) )  
                      {  
                          const Vector *pPoints = ToPoint(op)->GetPointR();  
                          LONG i, numPoints = ToPoint(op)->GetPointCount();  
                          mm.Init();  
                          for(i=0; i<numPoints; i++)  
                          {  
                              mm.AddPoint(*pPoints * opgm);  
                              pPoints++;  
                          }  
                      }  
                      else  
                      {  
                          //--------------------------------------------------------------------------------------------  
                          // ...otherwise, generate an 8 point OBB from the Global-space extent vectors  
                          //--------------------------------------------------------------------------------------------  
                          *pMin = op->GetMp() - op->GetRad(); // Bounding-Box minimum extents (Local-space)  
                          *pMax = op->GetMp() + op->GetRad(); // Bounding-Box maximum extents (Local-space)  
                      
                          // bottom  
                          mm.Init(*pMin * opgm);  
                          mm.AddPoint(Vector(pMin->x, pMin->y, pMax->z) * opgm);  
                          mm.AddPoint(Vector(pMax->x, pMin->y, pMax->z) * opgm);  
                          mm.AddPoint(Vector(pMax->x, pMin->y, pMin->z) * opgm);  
                      
                          // top  
                          mm.AddPoint(*pMax * opgm);  
                          mm.AddPoint(Vector(pMax->x, pMax->y, pMin->z) * opgm);  
                          mm.AddPoint(Vector(pMin->x, pMax->y, pMin->z) * opgm);  
                          mm.AddPoint(Vector(pMin->x, pMax->y, pMax->z) * opgm);  
                      }  
                      
                      // convert to AABBox (described by min/max extent vectors)  
                      *pMin = mm.GetMin();  
                      *pMax = mm.GetMax();  
                      
                    //    GePrint(op->GetName()+" bbMin: "+utVecToString(*pMin)+" bbMax: "+utVecToString(*pMax));  
                    }  
                      
                    Bool AABBox::CollidesWith(BaseObject *op)  
                    {  
                      if( !m_init )    return false;  
                      
                      Vector bbMin; // Bounding-Box minimum extents  
                      Vector bbMax; // Bounding-Box maximum extents  
                      
                      this->GetAABBox(op, &bbMin, &bbMax);  
                      
                      Bool xlap, ylap, zlap;  
                      if( bbMin.x < m_bbMax.x && bbMax.x > m_bbMin.x )    xlap = true;    else xlap = false;  
                      if( bbMin.y < m_bbMax.y && bbMax.y > m_bbMin.y )    ylap = true;    else ylap = false;  
                      if( bbMin.z < m_bbMax.z && bbMax.z > m_bbMin.z )    zlap = true;    else zlap = false;  
                      
                      //==================================================================================  
                      // output for testing purposes - delete or comment out it not needed  
                      String slap = op->GetName();  
                      slap += " xlap: ";                slap += xlap ? "true" : "false";  
                      slap += " ylap: ";                slap += ylap ? "true" : "false";  
                      slap += " zlap: ";                slap += zlap ? "true" : "false";  
                      slap += " BBox Collision: ";    slap += (xlap && ylap && zlap) ? "true" : "false";   
                      GePrint(slap);  
                      //==================================================================================  
                      
                      return (xlap && ylap && zlap);  
                    }  
                      
                    //==================================================================================  
                    // simple testing routine... builds AABBox from first object in scene (actually,  
                    // whatever object you pass to it), then tests for collisions with all other  
                    // (root level) objects below it in scene (but doesn't really do anything with  
                    // the results)  
                    //==================================================================================  
                    void BBoxTest(BaseObject *op)  
                    {  
                      if( op )  
                      {  
                          AABBox aabb(op);  
                      
                          BaseObject *op2 = op->GetNext();  
                          LONG collisions = 0;  
                          while( op2 )  
                          {  
                              collisions += aabb.CollidesWith(op2);  
                              op2 = op2->GetNext();  
                          }  
                      }  
                    }  
                      
                    //==================================================================================  
                    // simple testing routine to recursively walk the heirarchy, adding each object to  
                    // the AABBox, to generate a single / cumulative bounding box.  
                    //==================================================================================  
                    void AccumulateBBox(AABBox *aabb, BaseObject *op)  
                    {  
                      if( !aabb )    return;  
                      
                      while(op)  
                      {  
                          aabb->AddObject(op);  
                          AccumulateBBox(aabb, op->GetDown());  
                          op = op->GetNext();  
                      }  
                    }  
                    

                    ...I didn't include any code to call the bottom two test routines, but it should be pretty straight-forward.  Note that you can also get the min/max vectors from the AABBox (which would be in Global-space).

                    Cheers.

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

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

                      On 13/09/2012 at 06:33, xxxxxxxx wrote:

                      Giblet, you made my day. Thank you very very much! 🍺
                      I actually need C++, I was just prototyping in Python. 🙂

                      -Niklas

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

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

                        On 13/09/2012 at 06:37, xxxxxxxx wrote:

                        Someone mentioned Generators (and Deformers and such)... I hadn't really looked into that, so you might still need to add code to ctso some objects, etc.  Alternatively, you might just doc->Polygonize() first and use that (ctso on the entire doc).

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

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

                          On 14/09/2012 at 08:15, xxxxxxxx wrote:

                          Hei folks,

                          in case someone needs it: Here's the working version of the above scene-file using Giblets method (but using GetRad()/GetMp() only!!)

                          Cheers,
                          -Niklas

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

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

                            On 14/09/2012 at 11:46, xxxxxxxx wrote:

                            Thanks - it's neat seeing it (working and) ported to Python :). Did you try the full object point-transform method?

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

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

                              On 14/09/2012 at 12:55, xxxxxxxx wrote:

                              Did you try the full object point-transform method?
                              Do you mean calculating the bounding-box of point-objects from its points? No. Because,

                              1. I'm pretty sure GetDimension() does this internally for polygon-objects.
                              2. For splines, the curves could exceed the bounding box defined only by the points.

                              -Nik

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

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

                                On 14/09/2012 at 13:17, xxxxxxxx wrote:

                                Originally posted by xxxxxxxx

                                ...1. I'm pretty sure GetDimension() does this internally for polygon-objects.

                                Hmm...

                                • Load your scene, delete the 2 cubes.
                                • Add a "Tube" object.
                                • Switch to Front view.
                                • Rotate the Tube 30deg or so clockwise.
                                • Make it editable (turn it into a Polygon Object).
                                • Grab a point and (in Move mode), pull the point up (at that angle).
                                • Observe that the top of the BBox is no longer 'tight' on the object (across the top/right sides).
                                  ...doing the point-transform method would tighten that box back up (if you needed that).
                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  On 26/06/2015 at 01:43, xxxxxxxx wrote:

                                  Oh i think this would solve my problem with this

                                  https://developers.maxon.net/forum/topic/6903/7745_eventadd-doesnt-update-c4d

                                  Not the topic the solution from NiklasR, but The Python c4d file is 404 missing, here.

                                  Anyhow does somebody have a multiple objects boundingbox Python Script Snippet?

                                  Kind regards
                                  mogh

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