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

    Variable size BaseArray in Hyperfile [SOLVED]

    SDK Help
    0
    6
    625
    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 05/12/2016 at 07:49, xxxxxxxx wrote:

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

      ---------
      Hello,

      I would like to cache a BaseArray of vectors at every frame in the scene file, similar to particle system caching. I thought about using a Hyperfile for that, where I store all the positions of the particles in a HF and retrieve them at will.
      If I use a fixed size BaseArray, I am able to cache the array. If on the other hand I change the size of the array and save the scene, upon scene open, I get an Incorrect File Structure error and the scene would not load.
      Here is the code I am using to test the caching:

        
      class myObject : public ObjectData
      {
      	...
        
      public:
      	maxon::BaseArray<Vector>myVectors; // define myVectors as a class member BaseArray
      	...
      }
        
      // Init
      Bool myObject::Init(GeListNode *node)
      {
      	...
      	myVectors.Resize(10);  
      	LONG aa = myVectors.GetCount();
        
      	for (LONG i=0; i<aa; i++) myVectors[i] = Vector(i);
      }
        
      // Read and Write the Hyperfile
      Bool myObject::Read(GeListNode *node, HyperFile *hf, LONG level)
      {
      	if (level>=0)
      	{
      		for (LONG i=0; i<myVectors.GetCount(); i++)   // I think the problem resides here...
      		{
      			hf->ReadLVector(&myVectors[i]);
      		}
      	}
      	return TRUE;
      }
        
      Bool myObject::Write(GeListNode *node, HyperFile *hf)
      {
      	for (LONG i=0; i<myVectors.GetCount(); i++) // and here...
      	{
      		hf->WriteLVector(myVectors[i]);
      	}
        
      	return TRUE;
      }
        
      // Message buttons to read into the console and write into the BaseArray
      Bool myObject::Message(GeListNode *node, LONG type, void *data)
      {
      	...
      	if (dc->id[0].id == HF_READ)
      	{			
      		print(myVectors); // print the vector array into the console
      	}
        
      	if (dc->id[0].id == HF_WRITE)
      	{				
      		myVectors.Resize(5);  			// here I am changing the size of the array
      		for (LONG i=0; i<5; i++) myVectors[i] = Vector(i);
      	}
      }
        
        
      
      

      Is the proper way of caching a BaseArray into the scene file?
      How can I solve the variable size error that I am getting?

      Thanks!

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

        On 05/12/2016 at 09:28, xxxxxxxx wrote:

        Upon saving the file your Write() function only stores 5 vector values. But in your Read() function (when c4d loads the stored file) you want to read in 10 vector values. So when it tries to read the 6th vector value (which is not available in the hyperfile as you only have stored 5 values previously) ReadLVector() will return false. C4D notices this and stops the reading of the file as obviously something is wrong. Then the dialog message as you describe it will appear.

        You can fix this easily by first writing the amount of vector values you are writing in Write(). And then in Read() use it to dynamically resize your container before writing.

        Something like:

          
        Bool myObject::Write(..)  
        {  
           if(!hf->WriteInt32(myVectors.GetCount())) return false; //Write the array size  
           //... rest as before  
        }  
          
        Bool myObject::Read(...)  
        {  
           Int32 stored_cnt = 0; if(!hf->ReadInt32(&stored_cnt)) return false;  
           myVectors.resize(stored_cnt); //Now resize to the actual stored amount of vector values  
          
           for(Int32 i = 0; i < stored_cnt; ++i) //only iterate up to stored count. Or rather use array iterators  
           //...rest as before  
        }  
        
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 05/12/2016 at 10:27, xxxxxxxx wrote:

          Thank you Samir, it works.

          Since I never used Hyperfiles before, can you please clarify how hf->WriteInt32(myVectors.GetCount()) and  hf->ReadInt32(&stored_cnt) are referring to the same thing? I am finding it confusing since we did not specify a class member variable for that. What if I had 2 Int32 values that I needed to write? Sorry if this seems like a stupid question.

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

            On 05/12/2016 at 11:24, xxxxxxxx wrote:

            The Write() function of your object is called whenever the c4d scene file is saved by the user.
            And Read() is called whenever the scene file is loaded into c4d.

            Hyperfiles use FIFO (first in first out) style storage. This means, the first value (no matter the type) you write to the hyperfile in your Write() function, is also the first value you need to read in your Read() function.

            So you must read your data in the same order that you have written them into the hyperfile.

            And hf->WriteInt32(myVectors.GetCount()) is the first data value we write into the hyperfile.
            So hf->ReadInt32(&stored_cnt) is the first data value we need to read from the hyperfile.

            That way we know the basearray element count when the file was saved and we can resize it accordingly.

            And I am not sure I understand. We did not specify a class member variable for what?

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

              On 05/12/2016 at 11:26, xxxxxxxx wrote:

              If you wanted to write 2 Int values, just follow the FIFO style.

              Write()  
              {  
                hf->WriteInt32(an_integer_value);  
                hf->WriteInt32(another_integer_value);  
                hf->WriteFloat32(a_float_value);  
              }  
                
              Read()  
              {  
                Int32 a,b,c;  
                hf->ReadInt32(&a);  
                hf->ReadInt32(&b);  
                hf->ReadInt32(&c); //<-- Will fail! It expects us to read in a Float32 value (see Write() above)  
              }
              
              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 05/12/2016 at 11:53, xxxxxxxx wrote:

                Makes perfect sense now. Thanks again!

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