1
+ import bpy
2
+ import random
3
+ from gradio_client import Client
4
+
5
+ bl_info = {
6
+ "name" : "Autosculptor 3D Model Generator" ,
7
+ "blender" : (2 , 80 , 0 ),
8
+ "category" : "Object" ,
9
+ }
10
+
11
+ class GeneratorOperator (bpy .types .Operator ):
12
+ bl_idname = "object.autosculptor_model_generator"
13
+ bl_label = "Generate 3D Model"
14
+ bl_options = {'REGISTER' , 'UNDO' }
15
+
16
+ def execute (self , context ):
17
+ # Import properties from context
18
+ autosculptor_props = context .scene .autosculptor_props
19
+
20
+ prompt = autosculptor_props .prompt
21
+ seed = autosculptor_props .seed
22
+ if autosculptor_props .random_seed :
23
+ seed = random .randint (0 , 2147483647 )
24
+ guidance_scale = autosculptor_props .guidance_scale
25
+ num_inference_steps = autosculptor_props .num_inference_steps
26
+ model_type = autosculptor_props .model_type
27
+
28
+ # Shape-E model
29
+ if model_type == "shape-e-text" :
30
+ client = Client ("hysts/Shap-E" )
31
+ result = client .predict (
32
+ prompt = prompt ,
33
+ seed = seed ,
34
+ guidance_scale = guidance_scale ,
35
+ num_inference_steps = num_inference_steps ,
36
+ api_name = "/text-to-3d"
37
+ )
38
+ model_path = result
39
+
40
+ else :
41
+ self .report ({'ERROR' }, "Invalid model type." )
42
+ return {'CANCELLED' }
43
+
44
+ # Load the generated model
45
+ bpy .ops .import_scene .gltf (filepath = model_path )
46
+
47
+ # Ensure an object has been imported
48
+ if not bpy .context .selected_objects :
49
+ self .report ({'ERROR' }, "No object was imported." )
50
+ return {'CANCELLED' }
51
+
52
+ # Get the imported object (parent)
53
+ parent_obj = bpy .context .selected_objects [0 ]
54
+
55
+ # Find mesh object
56
+ obj = None
57
+ if parent_obj .children :
58
+ for child in parent_obj .children :
59
+ if child .type == 'MESH' :
60
+ obj = child
61
+ break
62
+
63
+ if obj is None :
64
+ self .report ({'ERROR' }, "No mesh object found among imported children." )
65
+ return {'CANCELLED' }
66
+
67
+ # Create a new material
68
+ material = bpy .data .materials .new (name = "ImportedMaterial" )
69
+ material .use_nodes = True
70
+
71
+ # Initialize Principled BSDF node
72
+ bsdf = None
73
+ for node in material .node_tree .nodes :
74
+ if isinstance (node , bpy .types .ShaderNodeBsdfPrincipled ):
75
+ bsdf = node
76
+ break
77
+ if bsdf is None :
78
+ bsdf = material .node_tree .nodes .new (type = 'ShaderNodeBsdfPrincipled' )
79
+
80
+ # Create an attribute node
81
+ attribute_node = material .node_tree .nodes .new ('ShaderNodeVertexColor' )
82
+ if obj .data .vertex_colors :
83
+ attribute_node .layer_name = obj .data .vertex_colors [0 ].name
84
+ else :
85
+ attribute_node .layer_name = "Color"
86
+
87
+ # Assign the material to the object
88
+ material .node_tree .links .new (attribute_node .outputs ['Color' ], bsdf .inputs ['Base Color' ])
89
+
90
+ if obj .data .materials :
91
+ obj .data .materials [0 ] = material
92
+ else :
93
+ obj .data .materials .append (material )
94
+
95
+ return {'FINISHED' }
96
+
97
+ class GeneratorPanel (bpy .types .Panel ):
98
+ bl_label = "Autosculptor"
99
+ bl_idname = "OBJECT_PT_autosculptor_model_generator"
100
+ bl_space_type = 'VIEW_3D'
101
+ bl_region_type = 'UI'
102
+ bl_category = 'Autosculptor'
103
+
104
+ def draw (self , context ):
105
+ layout = self .layout
106
+ scene = context .scene
107
+ autosculptor_props = scene .autosculptor_props
108
+
109
+ layout .prop (autosculptor_props , "prompt" )
110
+ layout .prop (autosculptor_props , "seed" )
111
+ layout .prop (autosculptor_props , "random_seed" )
112
+ layout .prop (autosculptor_props , "guidance_scale" )
113
+ layout .prop (autosculptor_props , "num_inference_steps" )
114
+ layout .prop (autosculptor_props , "model_type" )
115
+ layout .operator ("object.autosculptor_model_generator" )
116
+
117
+ class GeneratorProperties (bpy .types .PropertyGroup ):
118
+ prompt : bpy .props .StringProperty (name = "Prompt" )
119
+ seed : bpy .props .IntProperty (name = "Seed" , default = 0 , min = 0 , max = 2147483647 )
120
+ random_seed : bpy .props .BoolProperty (name = "Random Seed" , default = True )
121
+ guidance_scale : bpy .props .IntProperty (name = "Guidance Scale" , default = 15 , min = 1 , max = 20 )
122
+ num_inference_steps : bpy .props .IntProperty (name = "Inference Steps" , default = 64 , min = 2 , max = 100 )
123
+ model_type : bpy .props .EnumProperty (
124
+ name = "Model" ,
125
+ items = [
126
+ ("shape-e-text" , "Shap-E" , "hysts/Shap-E" )
127
+ ],
128
+ default = "shape-e-text"
129
+ )
130
+
131
+ def register ():
132
+ bpy .utils .register_class (GeneratorOperator )
133
+ bpy .utils .register_class (GeneratorPanel )
134
+ bpy .utils .register_class (GeneratorProperties )
135
+ bpy .types .Scene .autosculptor_props = bpy .props .PointerProperty (type = GeneratorProperties )
136
+
137
+ def unregister ():
138
+ bpy .utils .unregister_class (GeneratorOperator )
139
+ bpy .utils .unregister_class (GeneratorPanel )
140
+ bpy .utils .unregister_class (GeneratorProperties )
141
+ del bpy .types .Scene .autosculptor_props
142
+
143
+ if __name__ == "__main__" :
144
+ register ()
0 commit comments