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

    Smoothing vertex map

    Scheduled Pinned Locked Moved PYTHON Development
    5 Posts 0 Posters 879 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

      On 15/12/2017 at 08:00, xxxxxxxx wrote:

      In a ObjectData plugin, I create a vertex map from a polygon selection and put that in a vertex map tag.
      No problem so far, except that all the weights are set to 0% or 100%. There is no smoothing!

      So, how can I smooth the weights in the vertex map tag?

      I tried to do it using the paint tool, see below, but that gave me the warning "RuntimeError: illegal operation, invalid cross-thread call".
      Is there another way to smooth the vertex map?

      tool = c4d.plugins.FindPlugin(doc.GetAction(), c4d.PLUGINTYPE_TOOL)
      if tool is not None:
         tool[c4d.ID_BRUSH_BASE_TOOL_STRENGTH] = 1.0
         tool[c4d.ID_CA_PAINT_TOOL_MODE] = c4d.ID_CA_PAINT_TOOL_MODE_SMOOTH #smooth
         c4d.CallButton(tool, c4d.ID_CA_PAINT_TOOL_APPLY_ALL)
      
      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 15/12/2017 at 08:22, xxxxxxxx wrote:

        I guess you already know, but for peoples who get here, I told it .But it fail cause you are using c4d.CallButton from a threaded function (probably GetVirtualObject in your case).

        A workaround could be to use Message function explain here. But I'm really not sure it will work since it's a tool and not a NodeData in your case.

        But it's maybe time for asking how SendModelingCommand work? ^^

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 15/12/2017 at 08:35, xxxxxxxx wrote:

          Thanks for the reply.
          I considered SendModelingCommand, but I could not see how to use the paint tool and SendModelingCommand.

          Hopefully the guys from Maxon can explain.

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 18/12/2017 at 12:25, xxxxxxxx wrote:

            Hi Pim,

            As gr4ph0s already told you, it's not allowed to interact with a tool from an object plugin. Also the Paint Tool can't be used with SendModelingCommand().

            The solution is to manually smooth the weights just like the Paint Tool does when clicking the Apply buttons.

            Don't be afraid, the needed code isn't complex.
            You can find a script below. It first initializes the selected points with a weight of 1.0. Then it performs the smoothing with the average of the neighboring points weight.
            Code works with a polygon object which has polygons selected.

            Note if you'll be using this code in a generator, then don't call SetBit(c4d.BIT_ACTIVE) on the vertex map tag and EventAdd().
            These functions are forbidden there and also it would not make sense to call these as the vertex map tag is used virtually.

            import c4d
              
              
            def main() :
                # Requirements
                
                if op is None:
                    return
                
                if op.GetType() != c4d.Opolygon:
                    return
                
                if doc.GetMode() != c4d.Mpolygons:
                    return
                
                # Retrieve polygon object information
                
                allPolys = op.GetAllPolygons()
                polyCount = op.GetPolygonCount()
                if len(allPolys) != polyCount:
                    return
                
                polySel = op.GetPolygonS()
                
                # Select points from polygon selection
                pointSel = c4d.BaseSelect()
                for polyIdx in xrange(polyCount) :
                    if not polySel.IsSelected(polyIdx) :
                        continue
                    
                    pointSel.Select(allPolys[polyIdx].a)
                    pointSel.Select(allPolys[polyIdx].b)
                    pointSel.Select(allPolys[polyIdx].c)
                    pointSel.Select(allPolys[polyIdx].d)
                
                # Add vertex map tag to polygon object
                pointCount = op.GetPointCount()
                vmapTag = op.MakeVariableTag(c4d.Tvertexmap, pointCount)
                if vmapTag is None:
                    return
                
                # Initialize vertex map for selected points with 1.0 weight
                vmapData = vmapTag.GetAllHighlevelData()
                for pointIdx in xrange(pointCount) :
                    if not pointSel.IsSelected(pointIdx) :
                        continue
                    
                    vmapData[pointIdx] = 1.0
                
                # Create list for the new vertex map data
                newData = [0.0] * pointCount
                
                # Strength of weight application (Opacity in Paint Tool)
                applyStrength = 1.0
                
                # Create neighbor to obtain information on neighboring polygons for each point
                nb = c4d.utils.Neighbor()
                if not nb.Init(op) :
                    return
                
                # Smooth calculation loop
                for pointIdx in xrange(pointCount) :
                    if not pointSel.IsSelected(pointIdx) :
                        continue
                    
                    # Get neighboring polygons
                    polys = nb.GetPointPolys(pointIdx)
                    if len(polys) == 0:
                        newData[pointIdx] = vmapData[pointIdx]
                        continue
              
                    # Select points from neighboring polygons
                    sel = c4d.BaseSelect()
                    for poly in polys:
                        sel.Select(allPolys[poly].a)
                        sel.Select(allPolys[poly].b)
                        sel.Select(allPolys[poly].c)
                        sel.Select(allPolys[poly].d)
                    
                    weight = 0.0
                    num = 0
                    
                    # Calculate average weight from neighboring points
                    segCount = sel.GetSegments()
                    for segIdx in xrange(segCount) :
                        first, last = sel.GetRange(segIdx, pointCount)
                        for idx in range(first, last+1) :
                            weight += vmapData[idx]
                            num += 1
                    
                    if num > 0:
                        weight /= float(num)
                    
                    # Blend weight
                    data = vmapData[idx]
                    value = data + (weight - data) * applyStrength
                    
                    # Set new weight
                    newData[pointIdx] = c4d.utils.ClampValue(value, 0.0, 1.0)
              
                # Finally set the new vertex map data
                vmapTag.SetAllHighlevelData(newData)
                # Update polygon object
                op.Message(c4d.MSG_UPDATE)
                
                vmapTag.SetBit(c4d.BIT_ACTIVE)
                c4d.EventAdd()
              
              
            if __name__=='__main__':
                main()
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 18/12/2017 at 13:07, xxxxxxxx wrote:

              Great, thank you!

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