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.
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.
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.
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.
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
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 Value: ' + 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 to modify in Blender code? I need to make patch for this or it’s somwhere in core folder in .py file?
It definitely should be the same values as in other programs to not confuse users…