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
    • Register
    • Login

    Faster way to transfer weights?

    SDK Help
    0
    12
    1.9k
    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 18/07/2018 at 02:58, xxxxxxxx wrote:

      Hi xfon5168, thanks for writing us.

      With regard to your question, the performance increase you're actually benefiting is, in large part, caused by the Python call layer being skipped. The design of the code and the functions used are pretty likely the same of your Python script which means that the business logic is exactly the same.

      A few notes though:

      • why are you calling WeightDirty twice in the for loop? Calling it at the end of the for-loop could be more efficient with, maybe, no side effects on the delivered functionality;
      • move the counter definition outside of the for-loop definition.

      Last but not least, without a proper time-logging of the different execution calls of your code, could be really argue to propose an optimal solution even considering the presence of multiple FindXXX and SearchXXX calls.

      Best, Riccardo

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

        On 18/07/2018 at 07:35, xxxxxxxx wrote:

        That all sounds reasonable. Get/SetWeightMap doesn't exist in python, so I couldn't use that before.

        However, I'm a little bit confused by GetWeightMap. What is the map flag in this case? For SetWeightMap that makes sense, but I don't understand what I need to pass in as the map key.

        I am basically trying to do:

        wt->SetWeightMap(targID, wt->GetWeightMap(sourceID), pointCount)
        

        But the docs suggest that GetWeightMap needs the ID, the map, and the pointCount. So what do I use for the map in this case? Or is the map in this case  singular value you are trying to flood? ie flood everything to 1 or 0.0? If that's the case then GetWeightMap won't work because I'm not trying to flood a map to a singular value, but instead copy all the weights from joint A and put them on joint B.

        Im sure the Search and Find calls are slow too. This is a prototype for a plugin. I've opted to use those simple calls to make it easier on myself to just test this to start. Eventually, there will be a UI where it controls what goes to where, etc.

        Thanks for your help so far.

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

          On 18/07/2018 at 10:30, xxxxxxxx wrote:

          Long story short, it's not a flag.

          C++ doesn't have multiple return values.  If you want to return multiple things, you pass by reference or by using pointers to allocated memory.

          It's also faster to do this.  When you return an array in Python, it allocates a new block of memory, fills it (often copying from something else), returns it, and then deallocates the original.  That's a lot of overhead.

          So think of the *map as your return value. You pass the function an array of floats, and it fills it. The array should be the same size as the number of points.

          Here's a C++11 example of how to do it.  I get the spot in memory (map.data()).  That is the same as using map[0].  If I want the next spot, I can do map.data() + 1, or map.data() + 2 for map[1] or map[2] respectively.

          #include <iostream>
          #include <vector>

          using namespace std;

          void test_func(int* something, int value) {
              *something = value;
          }

          int main(int argc, char** argv) {
              // here we allocate memory
              // using a vector means we don't have to worry about deallocating
              vector<int> map(3);
              test_func(map.data(), 15);
              test_func(map.data()+1, 30);
              test_func(map.data()+2, 45);
              
              cout << "The values are " << map[0] << ", " << map[1] << ", and " << map[2] << "." << endl;
              return 0;
          }

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

            On 18/07/2018 at 21:54, xxxxxxxx wrote:

            Hmmm. I added the includes, and using namespace std lines. Then I tried the following:

            vector<Float32> map(pointCount);
            	wt->SetWeightMap(targID, wt->GetWeightMap(sourceID, map, pointCount), pointCount);
            	wt->WeightDirty();
            

            But it is still complaining. It's saying argument type void incompatible with parameter type float32(This is for the wt in wt->GetWeightMap. and map says no suitable conversion from std::vector<Float32, std::allocator<Float32>> to Float 32 exists.

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

              On 19/07/2018 at 01:36, xxxxxxxx wrote:

              Hello,

              just a comment: it is not advised to use components of the standard library in a Cinema 4D plugin. Please use the API's components if needed e.g. BaseArray or HashMap.

              best wishes,
              Sebastian

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

                On 19/07/2018 at 07:19, xxxxxxxx wrote:

                Why is that?

                Especially in this case, provided the container isn't passed back out and is used only within the scope of the function, what is the difference between using it and a BaseArray?

                I'll side with you on HashMap over std::map since we all know std::map is way too slow. 🙂

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

                  On 19/07/2018 at 14:47, xxxxxxxx wrote:

                  I'm new, so you guys are all just talking a lot of greek to me.

                  How do I properly create the map key to be able to use wt.GetWeightMap to properly plug that result into wt.SetWeightMap? :).

                  I just want to be able to compare that method's speed vs what I had previously.

                  Follow up question, how come Get/SetWeightMap isn't available in Python? Is there any real reason why it could not be?

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

                    On 20/07/2018 at 02:08, xxxxxxxx wrote:

                    Hello,

                    using standard library components is not advised since the standard library uses/throws exceptions. And exceptions are a concept not supported/used by the Cinema API.

                    You find example on how to use GetWeightMap() in the CAWeightTag Manual.

                    best wishes,
                    Sebastian

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

                      On 20/07/2018 at 20:11, xxxxxxxx wrote:

                      Thanks for pointing me to that. It got my test up and running which is great. It appears to be substantially faster to run SetWeightMap.

                      Is there any reason or limitation why that function doesn't exist for Python?

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

                        On 23/07/2018 at 03:25, xxxxxxxx wrote:

                        Originally posted by xxxxxxxx

                        Is there any reason or limitation why that function doesn't exist for Python?

                        There's no reason or limitation preventing CAWeightTag.GetWeightMap()/SetWeightMap() not being available in Python. I added these functions to our list of missing stuff in the Python API.

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