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 26/07/2012 at 03:07, xxxxxxxx wrote:

      Ok, I agree with you. Sorry. 🙂
      I haven't found another way to do yet. And I don't think there is.

      -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 26/07/2012 at 05:22, xxxxxxxx wrote:

        no problem Nick, you gave me the answer I needed 🙂

        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 26/07/2012 at 07:45, xxxxxxxx wrote:

          I'm afraid it must be done recursively. I've asked the developers to make sure. I'll post my findings.

          cheers,
          Matthias

          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 27/07/2012 at 04:57, xxxxxxxx wrote:

            FYI, recursive calculation is the "official" way indeed, at least that's what the Coordinate Managers Size+ mode is doing.

            cheers,
            Matthias

            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 27/07/2012 at 07:19, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              I guess you need to calculate it recursively. Need a hint or a full solution?
              -Niklas

              Hey Niklas,
              I would like a hint or a solution if you don't mind providing one.🙂
              Because in this case I don't really know what you guys mean by the term "recursive".
              The definition I know of for that word is calling a function from within the same function. But I don't see how that relates to finding the dimensions of a null.

              -ScottA

              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 27/07/2012 at 07:55, xxxxxxxx wrote:

                In this case recursive just means to traverse the given hierarchy. Then you can get the bounding box of each child object and use this to calculate the bounding box of the whole hierarchy.

                cheers,
                Matthias

                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 11/09/2012 at 08:42, xxxxxxxx wrote:

                  I thought it would be far more easy. But the rotation-stuff drives me crazy. I can't get it to work properly. 😠
                  Could someone please help me on finding the correct algorithm? 🙂

                  Here's a small video on what I have achieved so far. As you can hardly see, the rotation is not taken in account correctly.

                  Here's the C4D File.

                  Thanks in advance,
                  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 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
                                            • First post
                                              Last post