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

    object Mg in a later frame

    SDK Help
    0
    8
    765
    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 07/03/2016 at 01:55, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R17 
      Platform:   Windows  ;   
      Language(s) :     C++  ;

      ---------
      Hello.

      I have my own renderer and whenever i have to render a C4D document for a specific frame (lets say frame 20), I use doc->ExecutePasses(thread, TRUE, TRUE, TRUE, BUILDFLAGS_EXTERNALRENDERER) to calculate the animation. The variables doc and thread are taken from VideoPostStruct parameter of VideoPost's Execute method.

      I have an effect that requires the object global matrices of future frames.

      So whenever I have to pass any object's matrix in my renderer, i do the following as well:

      BaseTime original_time = doc->GetTime();
      Int32 fps = doc->GetFps();
        
      doc->SetTime(BaseTime(future_frame , fps)); //set future frame
      doc->ExecutePasses(threa, TRUE, TRUE, TRUE, BUILDFLAGS_EXTERNALRENDERER);
      Matrix object_matrix = object.GetMg();
        
      doc->SetTime(original_time); //revert frame
      doc->ExecutePasses(NULL, TRUE, TRUE, TRUE, BUILDFLAGS_EXTERNALRENDERER);
        
      
      

      Is this the correct way to get the required global matrix from an object in specific future frame ?

      If I have hair in my scene, I execute passes for every frame from 0 to future_frame.

      Thank you for your time.

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

        On 08/03/2016 at 01:47, xxxxxxxx wrote:

        Hello,

        I don't think there is a "correct" or "official" way of handling this situation. The most correct solution would be to wait for the next frame and to get the matrix of the object then.

        I would strongly disadvise to manipulate the given BaseDocument this way. Depending on what you do elsewhere of what other post effects might be added, changing the BaseDocument this way could cause problems. It would be saver to do such operations (animation) on a copy of the given BaseDocument.

        If you work on a copy of the BaseDocument you might not need to rewind it (depending on how you work with it). If you rewind it, you also might rewind it if the document contains particles, thinking paticles or dynamics.

        Best wishes,
        Sebastian

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

          On 08/03/2016 at 05:36, xxxxxxxx wrote:

          Hello.

          Thank you for your response.
          Indeed I use a copy of the document.
          I set the time of the document only for the purposes of global matrix retrieval.
          Then i set it back in the original time in order to be used by the rest of the objects.

          Thank you.

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

            On 15/03/2016 at 02:02, xxxxxxxx wrote:

            Hello.

            By setting the doc's time to a future time I can get the future position of an object.
            But, there is a problem if the object stops existing in the future (in case it is generated by a cloner).

            Considering I have a BaseObject pointer retrieved in frame 30, how can I check if this object is still valid in frame 60 ? I have used SetFrame and ExecutePasses on the document. By getting its matrix via object.GetMg() I get a crash, because the object doesn't exist in that frame.

            How can I make a check if the object exists ?

            Thank you.

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

              On 15/03/2016 at 10:16, xxxxxxxx wrote:

              Hello,

              you should not store a pointer to any Cinema 4D scene element as a reference. To store a reference to an entity use a BaseLink object. That said, this might not work for virtual objects created by a generator since the generator may re-create the object at any time.

              A generator that creates multiple virtual objects should set a unique IP for each of these objects (see BaseObject::GetUniqueIP()). So you can try to use this IP to search for a specific object in a generator's cache at a certain time.

              Best wishes,
              Sebastian

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

                On 18/03/2016 at 01:32, xxxxxxxx wrote:

                Hello

                Originally posted by xxxxxxxx

                That said, this might not work for virtual objects created by a generator since the generator may re-create the object at any time.

                Is this going to be a problem even if the generator (or emitter) has been baked ?

                Originally posted by xxxxxxxx

                A generator that creates multiple virtual objects should set a unique IP for each of these objects (see BaseObject::GetUniqueIP()). So you can try to use this IP to search for a specific object in a generator's cache at a certain time.

                I use the GetUniqueIP but even if the object shouldn't exist, it still returns its initial IP value.

                Thank you for your time.

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

                  On 18/03/2016 at 08:28, xxxxxxxx wrote:

                  Hello.

                  Originally posted by xxxxxxxx

                  I use the GetUniqueIP but even if the object shouldn't exist, it still returns its initial IP value.

                  Allow me to correct this statement.
                  Considering that I have an emitter that generates 3 objects with lifetime 40 frames, whenever an object reaches the end of its lifetime, ALL objects change UniqueIP, even if they will not die for the rest of the track.

                  So, even though the BaseLink solution you mentioned before helps me to preserve the object, I cannot find a way to ensure that it has not passed its lifetime.

                  The best solution for me would be that the particle objects don't modify their unique IPs until the end of their lifetime. Is there any way to do that ?

                  Thank you for your time.

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

                    On 21/03/2016 at 04:45, xxxxxxxx wrote:

                    Hello,

                    are you talking about the standard particle emitter? I don't seem to have a problem with the unique IP of the cache objects. This is what I try:

                      
                    BaseObject* op = doc->GetActiveObject();  
                    if (!op || !op->IsInstanceOf(Oparticle))  
                      return false;  
                      
                    BaseObject* cache = op->GetCache();  
                    if(cache && cache->GetDown())  
                    {  
                      BaseObject* particle = cache->GetDown();  
                      while(particle)  
                      {  
                      GePrint("Unique IP: " + String::IntToString(particle->GetUniqueIP()));  
                      particle = particle->GetNext();  
                      }  
                    }  
                    

                    best wishes,
                    Sebastian

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