Matching Crease value in Blender with Other Softs (Visual only)

Wanted to start this topic long ago…(investigation starts from here), but I summarize:

If you’ve ever used creases and then exported the mesh to another soft, you’ve probably noticed that the crease value looked different.
It’s because

And for example, if you need creases to be 0.3 after import in other soft, you should do some calculation

Why so

We tried to call (or summon with @, what’s the correct word?) the developers for clarification.
It is clear that people are busy, so I am making a separate topic so that this issue will be noticed eventually.

What is the problem:
if new users (from other softs) modeling in blender with creases and automatically set the values thinking that it should be true, after export/import they find that value they set in blender 0.3 become 0.1 in other soft.

1 Like

Sergey told me that conversion between blender and linear crease value should be handled by exporter. So If there is confirmed case of wrong behavior, it should be filed as a bug against appropriate exporter.
I would not be surprised, if I/O maintainers aren’t fully aware of this little detail.

1 Like

But it’s not export/import case.
Example:
I set value 0.3 for Crease edge/s in Blender, then export file (with FBX).
Open other soft - import file, and value become 0.1

But visually creased edge not changed it look identical in Blender but with value 0.3.
The same way if I set value 0.3 in other soft and then import file in Blender the value become 0.547

So import/export works fine.

The problem is that you need calculate by yourself what value you should type in blender so that in other soft it is equal to the values 0.1 0.2 0.3, etc.

Does opensubdiv documentation say anything about creases? Or do they have test reference models somewhere? Ideally blender should match that.

Should not post link with documentation for other soft but google give me the first link with request “opensubdiv crease” for soft with 2020 in the name.
Other link not so useful opensubdiv

With google link it says:
if I set Crease value to 0.1 the edge would be completely sharp until my sds level is 1.
if I set Crease value to 0.5 the edge would be completely sharp until my sds level is <=5, after I set it 6 edge become little smooth.
And I confirm this behavior with two softs I used.

1 Like

But do not pay attention to this sds levels.
In Blender it works as intended but values should be precalculated (I don’t know how to say it correctly).

It just need visually change the representation of the value and that’s it.
If I type 0.1 in Blender crease field, it should input as square root of 0.1.
So I see 0.1 value, but blender see it like 0.31622776601

Played with conversion to match values, and got this:

Simple panel where we typing value that match crease in other soft and it automatically convert it.
As you can see I typed 0.4, in Blender it match 0.63
and it work as should, edges is completely sharp with Subdivision modifier until “sds level”<=4

Code here
import bpy, bmesh, math
from bpy.types import PropertyGroup, Panel

# Add-on info
bl_info = {
    "name": "Test Addon",
    "author": "USER",
    "version": (0, 0, 1),
    "blender": (2, 90, 0),
    "location": "View3D > Properties > Test Addon",
    "description": "", 
    "doc_url": "",
    "tracker_url": "",      
    "category": "3D View"
}

###########################################################################################
################################### Functions #############################################
###########################################################################################

class CREASE_PG_main(PropertyGroup):

    def update_edgeCrease(self, context):
        ''' Update function for edgeCrease property '''

        o  = bpy.context.object
        d  = o.data
        bm = bmesh.from_edit_mesh(d)

        creaseLayer = bm.edges.layers.crease.verify()

        if self.whoToInfluence == 'Selected Elements':
            selectedEdges = [e for e in bm.edges if e.select]
            for e in selectedEdges: 
                #e[creaseLayer] = self.edgeCrease
                e[creaseLayer] = math.sqrt(self.edgeCrease)
        else:
            for e in bm.edges: 
                #e[creaseLayer] = self.edgeCrease
                e[creaseLayer] = math.sqrt(self.edgeCrease)

        bmesh.update_edit_mesh(d)

    items = [
        ('All', 'All', ''),
        ('Selected Elements', 'Selected Elements', '')
    ]

    whoToInfluence: bpy.props.EnumProperty(
        description = "Influence all / selection",
        name        = "whoToInfluence",
        items       = items,
        default     = 'Selected Elements'
    )

    edgeCrease: bpy.props.FloatProperty(
        description = "Edge Crease",
        name        = "Set edge Crease",
        min         = 0.0,
        max         = 1.0,
        step        = 10,
        default     = 0,
        update      = update_edgeCrease
    )    

def get_crease_selected():
    o  = bpy.context.object
    d  = o.data
    bm = bmesh.from_edit_mesh(d)

    creaseLayer = bm.edges.layers.crease.verify()

    selectedEdges = ""
    for e in bm.edges:
        if e.select:
            selectedEdges = (str(round(e[creaseLayer], 2)) + ' ')
    return selectedEdges

def get_crease_converted():
    o  = bpy.context.object
    d  = o.data
    bm = bmesh.from_edit_mesh(d)

    creaseLayer = bm.edges.layers.crease.verify()
    
    selectedEdges = ""
    for e in bm.edges:
        if e.select:
            selectedEdges = (str(round(pow((e[creaseLayer]), 2), 2)) + ' ')
    return selectedEdges
  
###########################################################################################
###################################### UI #################################################
###########################################################################################

class CREASE_PT_main(Panel):
    bl_label = "Edge Crease"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Test Addon'

#    @classmethod
#    def poll( self, context ):
#        ''' Only show panel if there is an active mesh object '''
#        return context.object and context.object.type == 'MESH'
 
    def draw( self, context ):
        layout = self.layout
        props  = context.scene.CREASE_PG_main # Create reference to property group
        
        col = layout.column(align = True)
        if context.active_object.mode == 'EDIT':                
            col.label(text='Converted Value:  ' + get_crease_converted())
            col.label(text='Blender Velue:      ' + get_crease_selected())
        if (context.active_object is not None) and (context.active_object.mode == 'OBJECT'):
            col.enabled = False
        col.prop(props, "edgeCrease")    
        
###########################################################################################
##################################### Register ############################################
########################################################################################### 
 
classes = (
            CREASE_PG_main,
            CREASE_PT_main,
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)
    
    bpy.types.Scene.CREASE_PG_main = bpy.props.PointerProperty(type = CREASE_PG_main)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)

if __name__ == "__main__":
    register()

How to find this value in Blender code?