Particle system and SetMatrix_Matrix



  • 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



  • 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! :)



  • 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?



  • 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. ^^



  • 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.



  • 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 ! :D

    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



  • 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.



  • 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) 🤢



  • 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!



  • 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



  • 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



  • 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



  • 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



  • 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



  • 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



  • 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



  • 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


Log in to reply