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
    • Recent
    • Tags
    • Users
    • Login

    Particle system and SetMatrix_Matrix

    Scheduled Pinned Locked Moved SDK Help
    17 Posts 0 Posters 1.7k 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 02/06/2011 at 08:23, xxxxxxxx wrote:

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

      ---------
      Like several others here have done, I'm trying to write my own particle system. At the moment I have got it to the stage where particles are emitted, move as required, and die at the right point. However, it all falls down when I move/rotate my emitter object while the particles are being emitted.

      What should happen is that the particles emitted up to the point I move the emitter carry on in the direction they were moving before the move. What actually happens is that, for example, if I move the emitter along the X-axis, *all* the particles - new and old - are moved that distance along X as well.

      Here's the very simple draw code in the plugin (it's a generator plugin). The object 'pt' is an array of particles:

        
      DRAWRESULT MyParticle::Draw(BaseObject *op, DRAWPASS drawpass, BaseDraw *bd, BaseDrawHelp *bh)   
      {   
           LONG i;   
           Matrix mx;   
        
           if(drawpass != DRAWPASS_OBJECT)   
                return DRAWRESULT_SKIP;   
        
           mx = bh->GetMg();   
           bd->SetMatrix_Matrix(NULL, mx);   
           for(i = 0; i < particleCount; i++)   
           {   
                if(pt[i].alive)   
                     bd->DrawSphere(pt[i].off, pt[i].size, pt[i].col, 0);   
           }   
        
           return DRAWRESULT_OK;   
      }   
      

      The particle class is a subclass of the C4D Particle class and the initial position of the particle is set relative to the emitter position. I'm a bit puzzled as to how I correct this behaviour. What it seems I need to do is convert the particle position into a global position rather than a relative one, but is that the right approach? Am I using SetMatrix_Matrix correctly? I'd be grateful for any pointers in the right direction!

      Steve

      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 02/06/2011 at 12:16, xxxxxxxx wrote:

        Im not absolutely sure, but:
        Set mx.off to Vector(0) and it should work! 🙂

        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 02/06/2011 at 12:40, xxxxxxxx wrote:

          Many thanks for the reply. Unfortunately I've tried this now and it doesn't make any difference.

          It's really odd and I'm sure it's my lack of understanding of 3D maths. When a particle is generated it's set to have a position (which I've changed now to be an absolute position, rather than relative to the emitter). When each particle is drawn though, it appears always to have a position relative to the emitter. I assume that SetMatrix_Matrix is having this effect. But then how can I make my particles use an absolute position again?

          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 02/06/2011 at 12:54, xxxxxxxx wrote:

            Did you also try

            mx.off *= -1
            

            ?

            PS: But why do you want to let the particles where they are, but only for the position and not for the rotation ?
            If you can rotate your simulation, why not moving it ?

            PS2: What actually is the BaseDrawHelpers mx.off ? Is it the same as the Objects Position ? If not, the upper should be wrong, too. ^^

            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 02/06/2011 at 13:03, xxxxxxxx wrote:

              No, I haven't tried that but I will.

              Perhaps I didn't explain what I'm trying to do very well. What I want is for my system to work the same way as the C4D system does. If you create an emitter and hit play, then move or rotate the emitter, you see that only new particles are affected by the move or rotation. Already emitted particles aren't affected, they just keep on going in the same direction as when they were emitted. That's the result I want. What I'm getting is that *all* the particles are moved/rotated as though their position and direction was always relative to the emitter. The particles emitted before the emitter was moved don't carry on in their old direction and position, they are changed.

              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 02/06/2011 at 13:07, xxxxxxxx wrote:

                Ahhhhh, I understand ! 😄

                You must set the BaseDraw's Matrix to a global one, so the drawed particles are not drawed relative to your object.
                *But* you must emitt your particles relative to the objects Position.
                I hope this is right, haha. ^^

                I already wrote a 2D Particle Simulator, but it was not implemented into Cinema 4D.
                There, I had a class "system" organizing all stuff.
                An emitter did just add a particle to the system.

                If you want, I can provide you the Source. But it's Python. And 2Dimensional. 😉

                Cheers,
                Niklas

                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 03/06/2011 at 06:45, xxxxxxxx wrote:

                  Well, I seem to have resolved this. For anyone else undergoing the same pain, what I did was to change these lines:

                    
                       mx = bh->GetMg();   
                       bd->SetMatrix_Matrix(NULL, mx);   
                  

                  to this:

                    
                       bd->SetMatrix_Matrix(NULL, Matrix());   
                  

                  And now it works as intended. As to *why* it works... is beyond me. Some more documentation regarding SetMatrix_Matrix() and what it does and why it does it would be extremely helpful.

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

                    That's confusing. Setting the Matrix's off attribute to Vector(0,0,0) should have had the same effect,  (referring to the position of the particles, not the position by rotation) 🤢

                    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 03/06/2011 at 07:22, xxxxxxxx wrote:

                      Confusing... you're right enough there!

                      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/06/2011 at 07:28, xxxxxxxx wrote:

                        You should do all your particle calculation in global space. To make it work like Cinema's particle system each particle needs basically its own matrix, even if it's a reduced one. You then store the current position, direction etc. in the particle. To draw it you set the BaseDraw's transformation matrix to global space by passing the world axis (just a union matrix) to SetMatrix_Matrix().

                        bd->SetMatrix_Matrix(NULL, Matrix());
                        

                        Please have a look at the Particle class.

                        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/06/2011 at 07:46, xxxxxxxx wrote:

                          But why was this

                          mg.off = mg.v1 = mg.v2 = mg.v3 = Vector(0)
                          

                          not the same as

                          mg = Matrix()
                          

                          ?

                          Thanks,
                          Niklas

                          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/06/2011 at 07:51, xxxxxxxx wrote:

                            Originally posted by xxxxxxxx

                            But why was this

                            mg.off = mg.v1 = mg.v2 = mg.v3 = Vector(0)
                            

                            not the same as

                            mg = Matrix()
                            

                            ?

                            Because the Matrix() constructor initializes a unit matrix, like this:

                              
                            off = Vector(0.0);  
                            v1 = Vector(1.0, 0.0, 0.0);  
                            v2 = Vector(0.0, 1.0, 0.0);  
                            v3 = Vector(0.0, 0.0, 1.0);  
                            

                            EDIT: corrected some typos in the code

                            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/06/2011 at 08:11, xxxxxxxx wrote:

                              Thanks Matthias. In fact my particle class is a subclass of the C4D particle class, with position and direction set for each particle. The thing I was missing was setting the draw matrix to global space, although I got there in the end by trial and error.

                              The problem I'm having with these coordinate spaces is the different parameters SetMatrix_Matrix can take. For example, what is the difference between these various forms, some of which occur in the SDK examples:

                              SetMatrix_Matrix(op, Matrix());
                              SetMatrix_Matrix(NULL, Matrix());
                              SetMatrix_Matrix(op, bh->GetMg());
                              SetMatrix_Matrix(NULL, bh-GetMg());

                              They all seem to do something different but what? And if you have a moment could you give any guidance about when to use them, please?

                              Many thanks,

                              Steve

                              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 07/06/2011 at 02:38, xxxxxxxx wrote:

                                The second parameter, the matrix, is used to transform the vectors into global space.

                                Example: You have an object generator which should draw some handles in the view port. The handle vectors are in the object's local space. To bring them into global space they need to be multiplied with the object's global matrix. So in this case you pass the global matrix of the object, or even better the BaseDrawHelp's global matrix which is the cached object's global matrix.

                                Another example: You have a particle system and do all particle calculations in global space. So your particle vectors are already in global space. So the passed matrix needs to be just a unit matrix, which defines the world origin, to keep the vectors in global space.

                                So the thing to keep in mind is to pass the matrix to which your vectors are relative.

                                As for the first parameter, the object, I'm not sure. I will have to ask the developers.

                                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 07/06/2011 at 02:47, xxxxxxxx wrote:

                                  Matthias, that's really helpful - thank you. Now I understand what the second parameter does, it is clear what's going on and when I should use a world or object matrix.

                                  If you could ask the developers what the first parameter does, that would be very interesting.

                                  Kind regards,

                                  Steve

                                  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 08/06/2011 at 08:41, xxxxxxxx wrote:

                                    Originally posted by xxxxxxxx

                                    If you could ask the developers what the first parameter does, that would be very interesting.

                                    Ok, the first parameter just compares the passed pointer with the last internally stored pointer. This is used to avoid unnecessary matrix comparisions. If the pointers are different no matrix comparision occurs. Basically it's used for performance reasons. So if possible pass an object pointer.

                                    I will add this to the docs.

                                    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 09/06/2011 at 00:03, xxxxxxxx wrote:

                                      Right, got it, thank you very much.

                                      Steve

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