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
    • Register
    • Login
    1. Maxon Developers Forum
    2. indexofrefraction
    3. Posts
    • Profile
    • Following 0
    • Followers 0
    • Topics 35
    • Posts 133
    • Best 7
    • Controversial 0
    • Groups 0

    Posts made by indexofrefraction

    • Debug Scene / Generators (Scene heat map)

      Hi,

      is there any possibility to debug a slow scene?
      see which generators or other things use what processing time on scene refresh?
      i saw there is a "heat map" for nodes...
      something like this for the scene.

      best, index

      posted in Cinema 4D SDK windows macos
      indexofrefractionI
      indexofrefraction
    • RE: find out if generator object? (in case of a Field object)

      hi, i came up with this now...

      def hasGenFlag(op):
      	description = op.GetDescription(c4d.DESCFLAGS_DESC_NONE)		
      	bc = description.GetParameter(c4d.ID_BASEOBJECT_GENERATOR_FLAG)
      	return not bc[c4d.DESC_HIDE] if bc else False
      

      also its clear that "Generator" is a wide definition which doesn't match the Green Checkmark / Enabled GUI Element.
      in this sense the topic title is wrong bc i was just searching for a way to distinct objects having this GUI element from others which don't.
      (i can't change the topic title, i guess)

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: find out if generator object? (in case of a Field object)

      hey thanks for taking so much time for this ...

      for me it is only important to know if the gui element exists on the object...
      and its kind of awkward to have to change its state to figure that out.
      i fear that will trigger lots of stuff and slow down scenes even more
      (i have to check for many objects in complex scenes, and i can't know what obj types that are)

      is there no other way than disabling and re-enabling the object?

      in my experience c4d is very sensitive to object status changes and its easy to hog it down and make a scene unresponsive.

      EDIT : searching the objects Descriptions it is possible to find "Enable", but as mentioned Null Object has it too, it is just hidden.
      It would be very nice to be able to check if it is the right "Enabled" (there could be more) and if it is visible in the GUI.

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • find out if generator object? (in case of a Field object)

      hi,
      there is an old thread about this question:
      https://developers.maxon.net/forum/topic/6722/7354_find-out-if-generator-object
      with this conclusion :

      if obj.GetInfo() & c4d.OBJECT_GENERATOR:   
          print "a generator"   
      else:   
          print "not a generator"
      

      now i stumbled onto that Fields (eg. a Linear Field) do NOT qualify as generators in this test,
      but they DO have the green (enabled) checkmark that can be ticked on and off.

      is this a bug in the field objects ?
      or how can one find out if an object has the green checkmark or not ?

      best, index

      posted in Cinema 4D SDK python
      indexofrefractionI
      indexofrefraction
    • RE: How to Use GetConnectionValue/s() or GetConnection()?

      @ferdinand
      first of all, I understand your frustration, we just yesterday talked about the state of the Nodes API and are well aware of its hurdles for anything but super-experts.

      you can say that aloud!
      the whole system is very hard to understand. the only thing i got is all we know about traditional materials and even shaders is for the bin. node support evolved over time and most node examples do not work for people still using older c4d versions. also there are misc 3rd-party renderers that use different kinds of nodes / node systems. Drag & drop of attributes to the console doesn't work anymore, as well. the days of easy scripting are gone.. 😵

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Insert a shader into a shader hierarchy

      Thanks a lot kbar.. i'll watch and learn!
      still... the hurdles to compile a c++ plugin are extremely high nowadays. 😕
      it would be great if the sdk plugins would be downloadable ready compiled as well

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Insert a shader into a shader hierarchy

      this "Active Object Dialog" plugin looks very interesting
      if it would be understandably described how to compile it / the c++ sdk, we could check it out
      but sadly this got so complicated that you need a degree in IT to do it. .-)

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • developers.maxon.net - offline

      FYI, developers.maxon.net is down since about 24 hours....

      posted in General Talk
      indexofrefractionI
      indexofrefraction
    • RE: Gimbal Lock Safe Target Expression

      I have found another way to do this, which is maybe better (?)
      because it seems to work around tackling with parallel vectors....

      LookAtCamera::Execute() translated to python ... 🙂
      https://github.com/PluginCafe/cinema4d_cpp_sdk_extended/blob/master/plugins/cinema4dsdk/source/tag/lookatcamera.cpp

      def lookat(op, target, pitch=True):
        ''' orient op to look at target '''
        local = (~(op.GetUpMg() * op.GetFrozenMln())) * target.GetMg().off - op.GetRelPos()
        hpb = c4d.utils.VectorToHPB(local)
        if not pitch: hpb.y = op.GetRelRot().y
        hpb.z = op.GetRelRot().z
        op.SetRelRot(hpb)
        c4d.EventAdd()
      

      It seems to work fine... but for clarity... after checking the Matrix Manual (see end of the page) ...
      https://developers.maxon.net/docs/py/2023_2/manuals/data_algorithms/classic_api/matrix.html?highlight=matrix

      Is this correct / covers all cases to get the targets position in local space?
      (~(op.GetUpMg() * op.GetFrozenMln())) * target.GetMg().off
      specifically.. what is
      m = utils.MatrixMove(op.GetAbsPos()) * utils.HPBToMatrix(op.GetAbsRot()) * utils.MatrixScale(op.GetAbsScale())
      in this context? (ps. GetAbsScale misses the brackets in the docs)

      and... is this the real code of the Target Tag ?

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Gimbal Lock Safe Target Expression

      Hi Ferdinand, yes all solved
      and sorry if the gimbal lock was a false interpretation of what was happening.
      From reading the old threads I thought the quaternion solution was mandatory to solve this.

      for clarity and as an example I'm including a comparison of
      your solution (working) and riccardos solution (showing the flip)

      spotLight.c4d

      but for me the case is closed...
      Thanks a lot for helping with this !

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Gimbal Lock Safe Target Expression

      Hi Ferdinand,

      thanks a lot, seems I'm not the only one missing the good weather outside .-)

      The code in the first lookat() function should be abs(ri.x - 1.0),
      this comes from the post in the mentioned link. I corrected that in the original post.
      (it was just missing in the post, my code had the ri.x)

      what I'm on to is a 2 axis ceiling spot.
      its a null with a python tag having a target link userdata, then inside a hierarchy with two axes.
      atm they are driven by 2 target tags (initialized by the pyTag) one needs pitch on, one needs pitch off.
      this works fine, but as i have 900 of these in a file,
      i am trying to get rid of the target tags and do all in the pyTag.
      I can post the file tomorrow.

      what happens with my lookat() is that if you move the target,
      the spot sometimes turns upside down 180 degrees and sticks in the ceiling.

      with lookatQ() the spot simply doesn't point in the correct direction.
      but it would be very interesting to learn how to do it with quaternions.

      edit: your solution seems to work nicely, btw!
      p.s. i guess ~ is normalise and % is the cross product

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • Gimbal Lock Safe Target Expression

      Hi,
      I have seen and as expected this was discussed already in the past, but I could not find any working example in this forum.

      I'd simply like to have a (gimbal lock safe) python replacement for the Target (Expression) Tag.

      I'm attaching what I have come up with until now...
      two versions #1 without , #2 with quaternion --> sadly #1 has gimbal issues and #2 fails completely
      both with a pitch lock like in the Target Tag --> sure this could be done more elegant .-)

      It was stated in one of the (below) mentioned threads, that support can't solve such problems for the users,
      but this would be such a valuable tool in the quiver that it might be an exception (?)

      best, index

      def lookat(op, target, pitchlock=0):
          ''' gimbal lock UNSAFE target expression
              this basically works, but results in axis flips sometimes '''
          r1 = op.GetRelRot() # backup
      
          p1 = op.GetMg().off # from
          p2 = target.GetMg().off # to
          tmp = c4d.Vector(0, 1, 0) # temp-up
          fo = (p2 - p1).GetNormalized() # forward
          ri = tmp.Cross(fo).GetNormalized() # right
          up = fo.Cross(ri).GetNormalized() # up
      
          # https://developers.maxon.net/forum/topic/11152/object-target-expression-in-python/2
          # try to mitigate gimbal-lock --> UNSAFE, RESULTS IN AXIS FLIPS !
          if (fo + tmp).z < 0: up.x = -up.x
          if abs(ri.x - 1.0) < 0.001: ri = -ri
      
          m = c4d.Matrix()
          m.v1 = ri
          m.v2 = up
          m.v3 = fo
          m.off = p1
          op.SetMg(m)
      
          if pitchlock:
              r = op.GetRelRot()
              op.SetRelRot(c4d.Vector(r.x, r1.y, r.z))
      
      def lookatQ(op, target, pitchlock=0):
          ''' quaternion based (gimbal lock safe ???) target expression
              sadly doesn't work and results in a wrong rotation '''
      
          r1 = op.GetRelRot() # backup
      
          p1 = op.GetMg().off # from
          p2 = target.GetMg().off # to
          tmp = c4d.Vector(0, 1, 0) # temp-up
          fo = (p2 - p1).GetNormalized() # forward
          ri = tmp.Cross(fo).GetNormalized() # right
          up = fo.Cross(ri).GetNormalized() # up
      
          # copied from
          # https://www.gamedev.net/forums/topic/613595-quaternion-lookrotationlookat-up/
          w = math.sqrt(1.0 + ri.x + up.y + fo.z) * 0.5
          w4_recip = 1.0 / (4.0 * w)
          x = (up.z - fo.y) * w4_recip
          y = (fo.x - ri.z) * w4_recip
          z = (ri.y - up.x) * w4_recip
      
          # given the above is correct, is this correctly applied here ???
          q = c4d.Quaternion()
          v = c4d.Vector(x, y, z)
          q.SetAxis(v, w)
          m = q.GetMatrix()
          m.off = p1
          op.SetMg(m)
      
          if pitchlock:
              r = op.GetRelRot()
              op.SetRelRot(c4d.Vector(r.x, r1.y, r.z))
      
      posted in Cinema 4D SDK python
      indexofrefractionI
      indexofrefraction
    • RE: Osubdivisionsurface ?

      ups, sorrryy. my bad .-)

      I know that list ... but LOL,
      now i cant find the object type for the Cloner Object 🦌

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • Osubdivisionsurface ?

      hi.. just to report....

      the object type for the Subdivision Surface object seems to be missing in the python and C++ sdk...

      c4d.Osubdivisionsurface = 1007455

      best, index

      posted in Cinema 4D SDK python
      indexofrefractionI
      indexofrefraction
    • RE: Insert a shader into a shader hierarchy

      hi Ferdinand,

      i noticed that there is actually an issue with excessive gelist heads....
      if you have this :

      <c4d.BaseShader object called 'Filter/Filter' with ID 1011128 at 0x7fcebe74eeb0>
      + <c4d.GeListHead object at 0x7fcebe787a70> branch 'Shaders'
      + + <c4d.LayerShader object called 'Layer/Layer' with ID 1011123 at 0x7fcebe787ab0>
      + + + <c4d.BaseShader object called 'Noise/Noise' with ID 1011116 at 0x7fcebe787b90>
      

      GetUp() on the LayerShader seems to return None,
      which is a problem if - like in this case - you need to know if a shader is in the middle inside a shader tree,
      or if it is at the top / a direct child of the material

      this makes something like this necessary to properly "insert" a shader ....

      if isinstance(target, c4d.BaseShader): 
          shader.InsertUnder(target)
      else:
          target.InsertShader(shader)
      
      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Copy LayerShader to a new Material

      tx ferdinand,
      and yes intertwined threads .-)

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Insert a shader into a shader hierarchy

      ok, i think i figured out my issue mentioned above ..
      it would be nice if this could be confirmed:

      materials and shaders can only have shader type nodes,
      there must be a shader gelist head at the beginning and followed by normal nodes.
      i guess this is was InsertShader() actually does.

      now if you InsertShader again in the middle of a tree, you get a second shader gelist head
      and as expected this the point is where my simple shader traversing failed.
      but.. if you insert the filter shader manually in the material manager,
      there is no second shader gelist head, just the one at the beginning.

      so i guess that c4d accepts both ways,
      but the proper way would be already to use InsertUnder if we're already in a shader type node list (?)
      using InsertShader in the middle of a shader list is not necessary and bad practice (?)
      a list with multiple shader gelist heads could (should?) be pruned of excessive heads (?)

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Copy LayerShader to a new Material

      trying myself...
      a walker as above is probably not possible
      but this might be something handy for others :

      def nodesToList(op, li=None):
        ''' returns a list of a complete shader tree '''
        if not li: li = []
        if isinstance(op, c4d.GeListNode):
          while op:
            if not isinstance(op, c4d.GeListHead):
              li.append(op)
            if op.GetBranchInfo():
              for branch in op.GetBranchInfo():
                li = nodesToList(branch["head"].GetDown(), type, li)
            li = nodesToList(op.GetDown(), type, li)
            op = op.GetNext()
        return li
      
      # example
      for op in nodesToList(Mat):
            print(op)
      
      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Copy LayerShader to a new Material

      I have a follow up question.... and post it here because of the sample code above...
      if that is not good, could you move it to a new thread?

      Isn't there a code example somewhere how to properly walk the shader tree?
      i struggle with extending a "simple" walker function like the one below

      also if there are different node types wouldnt that need/allow an argument on which ones to follow ?
      e.g. would it be possible to walk from doc.GetFirstObject() and just get the tags?
      and finally is the walker below at least ok for objects?
      (its not my code, just copied from some old library)

      def walker(op):
        if not op: return None
        if op.GetDown():
          return op.GetDown()
        while op.GetUp() and not op.GetNext():
          op = op.GetUp()
        return op.GetNext()
      
      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction
    • RE: Insert a shader into a shader hierarchy

      hm, actually i think the script does work correctly.

      i was additionally checking if the shader tree was correct
      and i was doing this using my own shader walker
      and it failed, it stopps walking after the Filter Shader

      if i use your PrintRelatedNodes() everything looks ok

      i will post a follow up question in the mentioned thread :
      https://developers.maxon.net/forum/topic/14056/copy-layershader-to-a-new-material/5

      posted in Cinema 4D SDK
      indexofrefractionI
      indexofrefraction