Accessing Lines in Sketch and Toon with Python



  • On 27/07/2018 at 09:44, xxxxxxxx wrote:

    Hello,
    I would like to randomize each line/stroke's color for Sketch and Toon.

    I'm taking a look through the Modifiers in the Sketch and Toon material and I'm trying to wrap my head around the Python expression. When I change the color there, it changes the color of a pixel in the stroke, not the color of the entire stroke's line.

    If I use this in the Editor:
    def main() :
        return c4d.Vector(randint(0, 255) / 256.0, randint(0, 255) / 256.0, randint(0, 255) / 256.0)

    I get a line of colored noise:

    Can anyone help me randomize the stroke color please? Thank you!



  • On 31/07/2018 at 06:27, xxxxxxxx wrote:

    Hi Blastframe, thanks for writing us.

    With regard to your question, first of all I warmly recommend to have a look at the Command section in this Cinema 4D Help page describing the Sketch and Toon outline color. There you'll be provided with the list of global variables that can be used inside the Python script to properly control the script execution.

    That said, using PntA and PntB, you can use the following code snippet to generate pseudo-random color per-stroke

    import c4d  
    #Welcome to the world of Python  
      
    POINT_OFFSET = 10000  
      
    # Given two points, calculates a pseudo-unique stroke index   
    # NOTE: the uniqueness depends on the offset value which should   
    # be greater than the maximum vertices point count
    def CalcIndex(a, b) :  
      p = 0  
      if a > b:  
          p = a * POINT_OFFSET + b    
      else:  
          p = b * POINT_OFFSET + a  
      return p  
      
    # Given an index and a component value, a pseudo-random number is returned
    # NOTE: the number returned is constant across frames and/or render buckets  
    def myrand(p, comp) :  
      f = float(p) / (256.0 + comp)  
      rand = f - int(f)  
      return rand  
      
    def main() :  
      p = CalcIndex(PntA, PntB)  
      return c4d.Vector(myrand(p, 0), myrand(p, 1), myrand(p, 2))  
    
    

    Beside the code, it's relevant to state that using a standard random generator - like randint() -, since the execution of the scripts happens per bucket and per frame you could end up in a stroke made of as many color as the number of buckets the stroke is rendered by. By using instead a pseudo-random function, which is in this case based on the index of the segment, you can end up with a consistent coloring across buckets and frames.

    Definitively the pseudo-number generator provided above is pretty simple but as a proof of concept it works as expected.

    Best, Riccardo



  • On 31/07/2018 at 23:07, xxxxxxxx wrote:

    This was exactly what I was seeking. Thank you very much, Riccardo!

    Originally posted by xxxxxxxx

    Hi Blastframe, thanks for writing us.

    With regard to your question, first of all I warmly recommend to have a look at the Command section in this Cinema 4D Help page describing the Sketch and Toon outline color. There you'll be provided with the list of global variables that can be used inside the Python script to properly control the script execution.

    That said, using PntA and PntB, you can use the following code snippet to generate pseudo-random color per-stroke

    import c4d  
    #Welcome to the world of Python  
     
    POINT_OFFSET = 10000  
     
    # Given two points, calculates a pseudo-unique stroke index   
    # NOTE: the uniqueness depends on the offset value which should   
    # be greater than the maximum vertices point count
    def CalcIndex(a, b) :  
      p = 0  
      if a > b:  
          p = a * POINT_OFFSET + b    
      else:  
          p = b * POINT_OFFSET + a  
      return p  
     
    # Given an index and a component value, a pseudo-random number is returned
    # NOTE: the number returned is constant across frames and/or render buckets  
    def myrand(p, comp) :  
      f = float(p) / (256.0 + comp)  
      rand = f - int(f)  
      return rand  
     
    def main() :  
      p = CalcIndex(PntA, PntB)  
      return c4d.Vector(myrand(p, 0), myrand(p, 1), myrand(p, 2))  
    
    

    Beside the code, it's relevant to state that using a standard random generator - like randint() -, since the execution of the scripts happens per bucket and per frame you could end up in a stroke made of as many color as the number of buckets the stroke is rendered by. By using instead a pseudo-random function, which is in this case based on the index of the segment, you can end up with a consistent coloring across buckets and frames.

    Definitively the pseudo-number generator provided above is pretty simple but as a proof of concept it works as expected.

    Best, Riccardo


Log in to reply