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
    • Login
    1. Maxon Developers Forum
    2. PMenich
    • Profile
    • Following 0
    • Followers 0
    • Topics 1
    • Posts 6
    • Best 0
    • Controversial 0
    • Groups 0

    PMenich

    @PMenich

    0
    Reputation
    9
    Profile views
    6
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    PMenich Unfollow Follow

    Latest posts made by PMenich

    • RE: Get MODATA_SIZE of Mograph Particles to Build Stacks of Geometry

      fairs. I thought this was a normal forum for sharing ideas and solving problems/challenges.
      Didn't really think about it being a support thing.
      My bad

      posted in Cinema 4D SDK
      PMenichP
      PMenich
    • RE: Get MODATA_SIZE of Mograph Particles to Build Stacks of Geometry

      wow. smackdown.
      Well, in the spirit of sharing, I managed to figure it out (with the help of AI) which I will attach here for any future users who might like to take a look.

      Type_On.c4d

      Pete

      (C4D user since V6)

      posted in Cinema 4D SDK
      PMenichP
      PMenich
    • RE: Get MODATA_SIZE of Mograph Particles to Build Stacks of Geometry

      Celebration was a bit premature. Doesn't work with text (MoText) - any ideas? Chat GTP seems flummoxed by this...

      import c4d
      import math
      import typing
      from c4d.modules import mograph
      
      def get_clone_info(op, index: int) -> typing.Tuple[c4d.Vector, c4d.Vector]:
          """Gets the world coordinates and bounding box size of the specified clone index."""
          moData: mograph.MoData = mograph.GeGetMoData(op)
          if moData is None:
              raise ValueError("MoData is None. Ensure this is a MoGraph object.")
          
          cloneMatrices: typing.List[c4d.Matrix] = moData.GetArray(c4d.MODATA_MATRIX)
          cloneOffsets: typing.List[float] = moData.GetArray(c4d.MODATA_CLONE)
          if len(cloneMatrices) != len(cloneOffsets):
              raise IndexError("Clone matrix and index arrays are not of equal length.")
      
          # Ensure the index is within the valid range
          if index < 0 or index >= len(cloneMatrices):
              raise IndexError(f"Index {index} is out of range for the number of clones {len(cloneMatrices)}.")
      
          cloneMatrix: c4d.Matrix = cloneMatrices[index]
          worldPosition: c4d.Vector = cloneMatrix.off
      
          # Get the bounding box size of the clone geometry
          boundingBoxSize: c4d.Vector = c4d.Vector(0, 0, 0)
          if op.GetTypeName() == "Text":
              # For Text objects, calculate the bounding box size of each letter
              textObject = op
              textObject.Update()
              bbox = textObject.GetBBox()
              if bbox:
                  min_point = bbox["min"]
                  max_point = bbox["max"]
                  min_point = min_point * cloneMatrix
                  max_point = max_point * cloneMatrix
                  boundingBoxSize = max_point - min_point
      
          print(f"Index: {index}, World Position: {worldPosition}, Bounding Box Size: {boundingBoxSize}")
          return worldPosition, boundingBoxSize
      
      def main():
          # Get the index from the user data slider
          index = op[c4d.ID_USERDATA, 1]  # Adjust the ID to match your user data field
      
          try:
              worldPosition, boundingBoxSize = get_clone_info(op, index)
              # Store the results in user data fields or custom data fields
              op[c4d.ID_USERDATA, 2] = worldPosition  # Adjust the ID to match your user data field for world position
              op[c4d.ID_USERDATA, 3] = boundingBoxSize  # Adjust the ID to match your user data field for bounding box size
          except Exception as e:
              print(f"Error: {e}")
              op[c4d.ID_USERDATA, 2] = c4d.Vector(0, 0, 0)
              op[c4d.ID_USERDATA, 3] = c4d.Vector(0, 0, 0)
      
      posted in Cinema 4D SDK
      PMenichP
      PMenich
    • RE: Get MODATA_SIZE of Mograph Particles to Build Stacks of Geometry

      Managed to get it working with the help of ChatGPT!
      GetCloneSize.c4d

      posted in Cinema 4D SDK
      PMenichP
      PMenich
    • RE: Get MODATA_SIZE of Mograph Particles to Build Stacks of Geometry

      Hey,
      I've been trying to unpick this project to achieve the result I need, but not getting anywhere.
      I'm trying to get the x and y size of individual clones, specifically text objects, so I can create a rectangle spline that moves form letter to letter (or word to word) and draws a box around each letter or word. Driven by an index number slider in xpresso.
      Any ideas?

      posted in Cinema 4D SDK
      PMenichP
      PMenich
    • Drive smooth rotation

      Hey, I've been trying to create a python node in xpresso to emulate this bit of code from the amazing Mr Ebberts...

      http://motionscript.com/articles/speed-control.html

      Here's the After Effects expression I'm trying to translate...

      spd = effect("Slider Control")("Slider");
      n = spd.numKeys;
      if (n > 0 && spd.key(1).time < time){
        accum = spd.key(1).value*(spd.key(1).time - inPoint);
        for (i = 2; i <= n; i++){
          if (spd.key(i).time > time) break;
          k1 = spd.key(i-1);
          k2 = spd.key(i);
          accum += (k1.value + k2.value)*(k2.time - k1.time)/2;
        }
        accum += (spd.value + spd.key(i-1).value)*(time - spd.key(i-1).time)/2;
      }else{
        accum = spd.value*(time - inPoint);
      }
      value + accum
      

      Here's where I'm at with my Python translation...

      from typing import Optional
      import c4d
      
      op: c4d.modules.graphview.GvNode # The Xpresso node
      doc: c4d.documents.BaseDocument # The document evaluating this node
      tp: Optional[c4d.modules.thinkingparticles.TP_MasterSystem] # Particle system
      
      def main():
          global Output1
          #Grab the host-object to the xpresso Tag
          Rect = op.GetNodeMaster().GetOwner().GetObject()
      
          #Get the UserData
          spd = Rect[c4d.ID_USERDATA,1]
      
          # Get the first animation track of the object
          track = Rect.GetFirstCTrack()
      
          # Get the animation curve of the track
          curve = track.GetCurve()
      
          # Get the number of keyframes on the curve
          n = curve.GetKeyCount()
      
          fps   = doc.GetFps()
          sFrame= doc.GetMinTime().GetFrame(fps)
          eFrame= doc.GetMaxTime().GetFrame(fps)
          name  = op.GetName()
          key = curve.GetKey(1)
          keyValue = key.GetValue()
          keyFrame = key.GetTime().GetFrame(fps)
          currentFrame = doc.GetTime().GetFrame(doc.GetFps())
          value = spd
      
      
        
          if n > 0 and curve.GetKey(1).GetTime().GetFrame(fps) < currentFrame:
              accum = curve.GetKey(1).GetValue() * (curve.GetKey(1).GetTime().Get() - sFrame)
              for i in range(2, n):
                  if curve.GetKey(i).GetTime().Get() > currentFrame:
                      break
                  k1 = curve.GetKey(i-1)
                  k2 = curve.GetKey(i)
                  accum += (k1.GetValue() + k2.GetValue()) * (k2.GetTime().Get() - k1.GetTime().Get()) / 2
              accum += (curve.GetValue(curve.GetKey(i-1).GetTime()) + curve.GetKey(i-1).GetValue()) * (currentFrame - curve.GetKey(i-1).GetTime().Get()) / 2
          else:
              accum = Input1 * (currentFrame - sFrame)
          
          print(Input1 + accum)
      
          Output1 = value + accum
      
      • There are loads of unnecessary variables in there btw - that was me just trying to figure this stuff out!

      Basically trying to drive rotation without using time as my driver. Now, I'm no programmer (as you'll soon find out!), but the attached project does work, but doesn't do what I want it to! When the UsrData 'speed' gets to 0 it should stop. And the rotation is meant to be smooth ramp up and then smooth ramp down.

      Any python geniuses out there got time to take a look and tell me where I'm going wrong?

      Smooth_Rotater.c4d

      posted in Cinema 4D SDK
      PMenichP
      PMenich