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

    BaseObject Size & Scale

    Scheduled Pinned Locked Moved SDK Help
    13 Posts 0 Posters 1.1k Views
    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 Offline
      Helper
      last edited by

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

      On 25/07/2012 at 05:32, xxxxxxxx wrote:

      c++

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

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

        On 25/07/2012 at 06:05, xxxxxxxx wrote:

        I think the best way would be to retrieve the object's ObjectData() and call ObjectData::GetDimension().

        ObjectData* data = (ObjectData* ) op->GetNodeData();  
        if (!data) return FALSE;  
        Vector mid, xyz;  
        data->GetDimension(op, &mid, &xyz);
        

        But be aware. I've found this statement in the SDK today under Stability & Testing > Virtual function calls:

        Originally posted by xxxxxxxx

        This Virtual Function Call will crash:

             PluginVideoPost \*node;   for (node = renderdata->GetFirstVideoPost(); node; node=node->GetNext())   {     VideoPostData \*pVPData = (VideoPostData\*=)node->GetNodeData();     LONG info = pVPData->GetRenderInfo();   }   

        • Beware of calling NodeData members!
        • pVPData can be NULL, check necessary
        • A plugin is not allowed to use the virtual function table of another plugin! This will only work with the same plugin, not over plugin boundaries

        To avoid crashes the call above must be replaced by:
        `  
          PluginVideoPost *node;
          for (node = renderdata->GetFirstVideoPost(); node; node=node->GetNext())
          {
            VideoPostData *pVPData = (VideoPostData*=)node->GetNodeData();
            if (!pVPData) continue;
          
            LONG info = ((pVPData->*((VIDEOPOSTPLUGIN* )C4DOS.Bl->RetrieveTableX(pVPData,0))->GetRenderInfo)(node);
          }

        I'd appreciate if someone from the official support could enlighten us if we need to use this method for the code above, too. And maybe also why a plugin isn't allowed to use another plugin's ObjectData?

        I'm using this method (directly calling the virtual function) in a plugin that is under development, currently, and I haven't recognized any crashes yet.

        Cheers,
        -Niklas

        PS: I think in the first code-example from the quoted documentation, the call to VideoPostData::GetRenderInfo() is missing the "node" argument.
        `

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

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

          On 25/07/2012 at 07:07, xxxxxxxx wrote:

          I think you'd better call BaseObject::GetRad(). No need to invoke ObjectData::GetDimension().

          Niklas, I'll ask the developers if this information is still valid.

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

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

            On 25/07/2012 at 07:25, xxxxxxxx wrote:

            @Yannick: Oh, I've obviously missed that method. 🙂
            Thank you! Maybe you want to append the piece of code I'm actually using:

            /** This function converts a hierarchy of BaseObjects into PolygonObjects  
              only. A list of VirtualObjectConnection's is created with the passed  
              allocation-function. Returns FALSE on error, TRUE on success.  
              
              :param origin: The object to start the conversion from.  
              :param hh: A HierarchyHelp instance is necessary which may be passed  
                      through from GetVirtualObjects().  
              :param desthead: A reference to a pointer that will be filled with the  
                      address of the head of the sequence.  
              :param desttail: A reference to a pointer that will be filled with the  
                      address of the tail of the sequence.  
              :param destroot: A pointer to a pointer that will be filled with the  
                      address to hierarchies top-most object, just as *op* but  
                      polygonized.  
              :param allocator: A pointer to a function that will allocate memory  
                      for the sequence of VirtualObjectConnection objects. **/  
            bool PolygonizeHierarchy(BaseObject* origin, HierarchyHelp* hh,  
                                   VirtualObjectConnection*& desthead,  
                                   VirtualObjectConnection*& desttail,  
                                   BaseObject** destroot, AllocatorProc allocator);  
              
            /** .. **/  
              
            bool PolygonizeHierarchy(BaseObject* origin, HierarchyHelp* hh,  
                                   VirtualObjectConnection*& desthead,  
                                   VirtualObjectConnection*& desttail,  
                                   BaseObject** destroot, AllocatorProc allocator) {  
              ROCKGEN_DEBUG_INFO("invoked");  
              
              // Ensure we can actually convert the object to geometry. Therefore, we  
              // have to check if the object is a generator, not a spline and when it  
              // is using it's input (OBJECT_INPUT flag) it must also be handled  
              // seperately.  
              LONG info = origin->GetInfo();  
              bool isgenerator = info & OBJECT_GENERATOR;  
              bool isspline    = info & OBJECT_ISSPLINE;  
              bool ispolygonal = info & OBJECT_POLYGONOBJECT;  
              
              // This flag is only set in connection with OBJECT_GENERATOR  
              bool isinput     = info & OBJECT_INPUT;  
              
              if (!(isgenerator && !isspline) && !ispolygonal) {  
                  return TRUE;  
              }  
              
              // The reference to the new polygonized object is stored in this variable.  
              BaseObject* new_object;  
              
              // When the object is already a PolygonObject, we will create a copy of it.  
              if (ispolygonal) {  
                  COPYFLAGS cloneflag = COPYFLAGS_NO_HIERARCHY | COPYFLAGS_NO_ANIMATION;  
                  new_object = (BaseObject* ) origin->GetClone(cloneflag, NULL);  
                  if (!new_object) return TRUE;  
              
                  // The object may have been "touched" before and may also have some  
                  // bit's that we don't want it to have. (E.g. BIT_ACTIVE will make  
                  // the object being highlighted as it was selected, although it  
                  // actually exists in the virtual-hierarchy of a Generator object).  
                  new_object->SetAllBits(0);  
              }  
              
              // Now, as we have already excluded the object being a spline or not  
              // generator, we can safely obtain the internal ObjectData from the object  
              // an create it's virtual objects which will be converted recursively.  
              else {  
                  ObjectData* data = (ObjectData* ) origin->GetNodeData();  
                  new_object = data->GetVirtualObjects(origin, hh);  
              
                  if (!new_object) return TRUE;  
                  if (!new_object->IsInstanceOf(Opolygon)) {  
                      // We have to create a temporary object, as after conversion,  
                      // we will have to free the object we've obtained by  
                      // ObjectData::GetVirtualObjects().  
                      // Note that we don't check if the object could be a spline or  
                      // similar, because this is done by the call to  
                      // PolygonizeHierarchy(). Yes, yes. It's well thought out. :)  
                      BaseObject* temp = NULL;  
                      PolygonizeHierarchy(new_object, hh, desthead, desttail, &temp,  
                                          allocator);  
                      // TODO: implement break-up when previous function-call returns FALSE.  
                      BaseObject::Free(new_object);  
                      new_object = temp;  
                  }  
              }  
              
              // The object obtained from the call to PolygonizeHierarchy() after  
              // obtaining an object from the ObjectData could be NULL. ;)  
              if (new_object) {  
                  // We will fill the value pointed by *destroot* with the current object  
                  // when the pointer is not NULL. Afterwards, we will set it to be NULL  
                  // so it's not overwritten by following calls to this function.  
                  if (destroot) {  
                      *destroot = new_object;  
                      destroot  = NULL;  
                  }  
              
                  // Well, the virtual object doesn't actually have the same position  
                  // as the original, so we need to adjust that.  
                  new_object->SetMl(origin->GetMl());  
              
                  // And now comes the tricky thing about generator objects that accept  
                  // objects as input. If the object is an input generator, we will NOT  
                  // go down it's actual hierarchy recursively, because they've been  
                  // touched by the original generator.  
                  if (!isinput) {  
                      BaseObject* temp;  
                      BaseObject* new_child;  
                      for (temp=origin->GetDown(); temp; temp=temp->GetNext()) {  
                          new_child = NULL;  
                          PolygonizeHierarchy(temp, hh, desthead, desttail, &new_child,  
                                              allocator);  
                          // TODO: implement break-up when previous function-call returns FALSE.  
                          if (new_child) new_child->InsertUnder(new_object);  
                      }  
                  }  
              
                  // Ok, we're almost done. The last thing we will need to do, is to  
                  // establish the connection of the original object with the new, virtual  
                  // object.  
                  VirtualObjectConnection* new_connection = (VirtualObjectConnection* )  
                          allocator(sizeof(VirtualObjectConnection));  
                  if (!new_connection) return FALSE;  
                  if (!desttail) {  
                      desttail = new_connection;  
                  }  
                  else {  
                      desttail->next = new_connection;  
                      desttail = desttail->next;  
                  }  
                  if (!desthead) desthead = desttail;  
                  new_connection->origin  = origin;  
                  new_connection->cache   = new_object;  
                  new_connection->normals = NULL;  
                  new_connection->seqinfo = NULL;  
              }  
              
              ROCKGEN_DEBUG_INFO("End with success.");  
              return TRUE;  
            }
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

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

              On 30/07/2012 at 11:25, xxxxxxxx wrote:

              @Yannick: Did you get an answer from the devs? 🙂

              Thanks,
              Nik

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

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

                On 31/07/2012 at 01:25, xxxxxxxx wrote:

                BaseObject::GetRad() is the correct way to obtain an object's dimension. For object hierarchies you need iterate through the object tree.

                https://developers.maxon.net/forum/topic/6493/6983_null-object-dimensions

                cheers,
                Matthias

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

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

                  On 05/08/2012 at 10:05, xxxxxxxx wrote:

                  Hello Yannick,

                  Could you please tell me what the devs answer is?

                  Ty, Nik

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

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

                    On 05/08/2012 at 12:15, xxxxxxxx wrote:

                    Matthias is official support, so you can be quite sure it's the most straight-forward answer NiklasR. And it indeed is GetRad().

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

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

                      On 05/08/2012 at 12:31, xxxxxxxx wrote:

                      Hello Samir,

                      it's not about the GetRad() topic. See the previous posts:

                      Originally posted by xxxxxxxx

                      I'd appreciate if someone from the official support could enlighten us if we need to use this method for the code above, too. And maybe also why a plugin isn't allowed to use another plugin's ObjectData?

                      Originally posted by xxxxxxxx

                      Niklas, I'll ask the developers if this information is still valid.

                      -Nik

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

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

                        On 05/08/2012 at 15:57, xxxxxxxx wrote:

                        Originally posted by xxxxxxxx

                        Originally posted by xxxxxxxx

                        To avoid crashes the call above must be replaced by:

                        PluginVideoPost *node;
                        for (node = renderdata->GetFirstVideoPost(); node; node=node->GetNext())
                        {
                        VideoPostData *pVPData = (VideoPostData*=)node->GetNodeData();
                        if (!pVPData) continue;

                        LONG info = ((pVPData->*((VIDEOPOSTPLUGIN* )C4DOS.Bl->RetrieveTableX(pVPData,0))->GetRenderInfo)(node);
                        }

                        I'd appreciate if someone from the official support could enlighten us if we need to use this method for the code above, too. And maybe also why a plugin isn't allowed to use another plugin's ObjectData?

                        The mentioned information is still correct as far as I know.

                        You should be aware that Cinema is a multi-threaded application. So a pointer might be valid in one thread but not in another. For example the user is rendering into the editor and the plugin is modifying the scene at the same time. This might lead to crashes.

                        cheers,
                        Matthias

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

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

                          On 06/08/2012 at 01:38, xxxxxxxx wrote:

                          Thank you Matthias! Ok, so that is why we have to call RetrieveTable, etc..
                          Unfortunately, it's a complicated line of code to remember. 😉

                          -Niklas

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