ginipick commited on
Commit
3aff1e6
Β·
verified Β·
1 Parent(s): 30b09aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -210
app.py CHANGED
@@ -4,8 +4,6 @@ import glob
4
  import json
5
  import numpy as np
6
  import trimesh
7
- import argparse
8
- from scipy.spatial.transform import Rotation
9
  from PIL import Image, ImageDraw
10
  import math
11
  import trimesh.transformations as tf
@@ -19,101 +17,37 @@ import spaces
19
  LOG_PATH = './results/demo'
20
  os.makedirs(LOG_PATH, exist_ok=True)
21
 
22
- def create_simple_rotation_animation(input_glb_path, output_glb_path, num_frames=30):
23
- """
24
- 원본 GLB νŒŒμΌμ— νšŒμ „ μ• λ‹ˆλ©”μ΄μ…˜μ„ μ μš©ν•œ μƒˆλ‘œμš΄ GLB 파일 생성
25
- """
26
- try:
27
- # GLB 파일 λ‘œλ“œ
28
- scene = trimesh.load(input_glb_path)
29
-
30
- if isinstance(scene, trimesh.Scene):
31
- # μ• λ‹ˆλ©”μ΄μ…˜ 적용 (첫 번째 ν”„λ ˆμž„λ§Œ μ‚¬μš©)
32
- angle = math.pi / 4 # 45도 νšŒμ „
33
-
34
- # μ”¬μ˜ λͺ¨λ“  λ©”μ‹œμ— νšŒμ „ 적용
35
- for node_name, transform, geometry_name in scene.graph.nodes_geometry:
36
- # 원본 μœ„μΉ˜ λ°±μ—…
37
- original_transform = scene.graph[node_name][0]
38
-
39
- # νšŒμ „ λ³€ν™˜ 계산
40
- rotation = tf.rotation_matrix(angle, [0, 1, 0])
41
-
42
- # μƒˆ λ³€ν™˜ = 원본 λ³€ν™˜ * νšŒμ „ λ³€ν™˜
43
- new_transform = np.dot(original_transform, rotation)
44
-
45
- # λ³€ν™˜ 적용
46
- scene.graph[node_name] = new_transform
47
-
48
- # νšŒμ „λœ GLB μ €μž₯
49
- scene.export(output_glb_path)
50
- print(f"Saved animated GLB to {output_glb_path}")
51
- return output_glb_path
52
-
53
- elif isinstance(scene, trimesh.Trimesh):
54
- # 단일 λ©”μ‹œμΈ 경우
55
- new_scene = trimesh.Scene()
56
-
57
- # λ©”μ‹œμ— νšŒμ „ 적용
58
- angle = math.pi / 4 # 45도 νšŒμ „
59
- rotation = tf.rotation_matrix(angle, [0, 1, 0])
60
- scene.apply_transform(rotation)
61
-
62
- # νšŒμ „λœ λ©”μ‹œλ₯Ό 씬에 μΆ”κ°€
63
- new_scene.add_geometry(scene)
64
-
65
- # 씬을 GLB둜 μ €μž₯
66
- new_scene.export(output_glb_path)
67
- print(f"Saved animated GLB to {output_glb_path}")
68
- return output_glb_path
69
-
70
- else:
71
- print(f"Unsupported format: {type(scene)}")
72
- return None
73
-
74
- except Exception as e:
75
- print(f"Error creating animation: {str(e)}")
76
- return None
77
-
78
  def create_textual_animation_gif(output_path, model_name, animation_type, duration=3.0, fps=30):
79
- """ν…μŠ€νŠΈ 기반의 κ°„λ‹¨ν•œ μ• λ‹ˆλ©”μ΄μ…˜ GIF 생성 - λ Œλ”λ§ μ‹€νŒ¨ μ‹œ λŒ€μ²΄μš©"""
80
  try:
81
- # κ°„λ‹¨ν•œ ν”„λ ˆμž„ μ‹œν€€μŠ€ 생성
82
  frames = []
83
  num_frames = int(duration * fps)
84
- if num_frames > 60: # λ„ˆλ¬΄ λ§Žμ€ ν”„λ ˆμž„μ€ νš¨μœ¨μ μ΄μ§€ μ•ŠμŒ
85
  num_frames = 60
86
 
87
  for i in range(num_frames):
88
- t = i / (num_frames - 1) # 0~1 λ²”μœ„
89
- angle = t * 360 # 전체 νšŒμ „
90
 
91
- # μƒˆ 이미지 생성
92
  img = Image.new('RGB', (640, 480), color=(240, 240, 240))
93
  draw = ImageDraw.Draw(img)
94
 
95
- # 정보 ν…μŠ€νŠΈ
96
  draw.text((50, 50), f"Model: {os.path.basename(model_name)}", fill=(0, 0, 0))
97
  draw.text((50, 100), f"Animation Type: {animation_type}", fill=(0, 0, 0))
98
  draw.text((50, 150), f"Frame: {i+1}/{num_frames}", fill=(0, 0, 0))
99
 
100
- # μ• λ‹ˆλ©”μ΄μ…˜ μœ ν˜•μ— λ”°λ₯Έ μ‹œκ°μ  효과
101
  center_x, center_y = 320, 240
102
  if animation_type == 'rotate':
103
- # νšŒμ „ν•˜λŠ” μ‚¬κ°ν˜•
104
  radius = 100
105
  x = center_x + radius * math.cos(math.radians(angle))
106
  y = center_y + radius * math.sin(math.radians(angle))
107
  draw.rectangle((x-40, y-40, x+40, y+40), outline=(0, 0, 0), fill=(255, 0, 0))
108
-
109
  elif animation_type == 'float':
110
- # μœ„μ•„λž˜λ‘œ μ›€μ§μ΄λŠ” 원
111
  offset_y = 50 * math.sin(2 * math.pi * t)
112
  draw.ellipse((center_x-50, center_y-50+offset_y, center_x+50, center_y+50+offset_y),
113
- outline=(0, 0, 0), fill=(0, 0, 255))
114
-
115
- elif animation_type == 'explode' or animation_type == 'assemble':
116
- # λ°”κΉ₯μͺ½/μ•ˆμͺ½μœΌλ‘œ μ›€μ§μ΄λŠ” μ—¬λŸ¬ λ„ν˜•
117
  scale = t if animation_type == 'explode' else 1 - t
118
  for j in range(8):
119
  angle_j = j * 45
@@ -127,16 +61,12 @@ def create_textual_animation_gif(output_path, model_name, animation_type, durati
127
  draw.ellipse((x-20, y-20, x+20, y+20), outline=(0, 0, 0), fill=(0, 255, 0))
128
  else:
129
  draw.polygon([(x, y-20), (x+20, y+20), (x-20, y+20)], outline=(0, 0, 0), fill=(0, 0, 255))
130
-
131
  elif animation_type == 'pulse':
132
- # 크기가 λ³€ν•˜λŠ” 원
133
  scale = 0.5 + 0.5 * math.sin(2 * math.pi * t)
134
  radius = 100 * scale
135
  draw.ellipse((center_x-radius, center_y-radius, center_x+radius, center_y+radius),
136
  outline=(0, 0, 0), fill=(0, 255, 0))
137
-
138
  elif animation_type == 'swing':
139
- # 쒌우둜 μ›€μ§μ΄λŠ” μ‚Όκ°ν˜•
140
  angle_offset = 30 * math.sin(2 * math.pi * t)
141
  points = [
142
  (center_x + 100 * math.cos(math.radians(angle_offset)), center_y - 80),
@@ -145,10 +75,8 @@ def create_textual_animation_gif(output_path, model_name, animation_type, durati
145
  ]
146
  draw.polygon(points, outline=(0, 0, 0), fill=(255, 165, 0))
147
 
148
- # ν”„λ ˆμž„ μΆ”κ°€
149
  frames.append(img)
150
 
151
- # GIF둜 μ €μž₯
152
  frames[0].save(
153
  output_path,
154
  save_all=True,
@@ -163,136 +91,66 @@ def create_textual_animation_gif(output_path, model_name, animation_type, durati
163
  print(f"Error creating textual animation: {str(e)}")
164
  return None
165
 
166
- def create_glb_with_animation(input_glb_path, animation_type, duration=3.0, fps=30):
167
- """
168
- μ—…λ‘œλ“œλœ GLB νŒŒμΌμ— μ• λ‹ˆλ©”μ΄μ…˜μ„ μ μš©ν•œ μƒˆλ‘œμš΄ GLB 파일 생성
169
- """
170
  try:
171
- base_filename = os.path.basename(input_glb_path).rsplit('.', 1)[0]
172
- output_glb_path = os.path.join(LOG_PATH, f"animated_{base_filename}.glb")
173
 
174
- # 원본 λͺ¨λΈ λ‘œλ“œ
175
  scene = trimesh.load(input_glb_path)
176
- print(f"Loaded GLB: {type(scene)}")
 
 
 
 
177
 
178
- # μ• λ‹ˆλ©”μ΄μ…˜ μœ ν˜•μ— 따라 처리
179
  if animation_type == 'rotate':
180
- # μ‹œκ³„λ°©ν–₯ 45도 νšŒμ „
181
- angle = math.pi / 4
182
- axis = [0, 1, 0] # YμΆ• (μˆ˜μ§μΆ•)
183
  elif animation_type == 'float':
184
- # 수직으둜 μ›€μ§μž„
185
- angle = 0
186
- axis = [0, 1, 0]
187
- # YμΆ• λ°©ν–₯으둜 이동
188
- if isinstance(scene, trimesh.Scene):
189
- for node_name, transform, geometry_name in scene.graph.nodes_geometry:
190
- # κ°€λ³κ²Œ μœ„λ‘œ 이동
191
- translation = tf.translation_matrix([0, 0.2, 0])
192
- original_transform = scene.graph[node_name][0]
193
- new_transform = np.dot(original_transform, translation)
194
- scene.graph[node_name] = new_transform
195
- elif isinstance(scene, trimesh.Trimesh):
196
- translation = tf.translation_matrix([0, 0.2, 0])
197
- scene.apply_transform(translation)
198
- elif animation_type == 'explode':
199
- # 각 λΆ€λΆ„μ˜ μ€‘μ‹¬μ—μ„œ μ•½κ°„ λ©€μ–΄μ§€κ²Œ
200
- angle = 0
201
- axis = [0, 1, 0]
202
- # μ˜€λΈŒμ νŠΈκ°€ μ—¬λŸ¬ 개일 경우 μ€‘μ‹¬μ—μ„œ λ°”κΉ₯μͺ½μœΌλ‘œ 이동
203
- if isinstance(scene, trimesh.Scene):
204
- # μ”¬μ˜ 쀑심점 계산
205
- all_vertices = []
206
- for geometry_name, geometry in scene.geometry.items():
207
- if hasattr(geometry, 'vertices') and len(geometry.vertices) > 0:
208
- all_vertices.append(geometry.vertices)
209
-
210
- if all_vertices:
211
- all_points = np.vstack(all_vertices)
212
- center = np.mean(all_points, axis=0)
213
-
214
- for node_name, transform, geometry_name in scene.graph.nodes_geometry:
215
- # 각 λΆ€λΆ„μ˜ 쀑심점 계산
216
- geometry = scene.geometry[geometry_name]
217
- if hasattr(geometry, 'centroid'):
218
- part_center = geometry.centroid
219
- # μ€‘μ‹¬μ—μ„œ 객체 λ°©ν–₯ 계산
220
- direction = part_center - center
221
- if np.linalg.norm(direction) > 0.001:
222
- direction = direction / np.linalg.norm(direction)
223
- # λ°©ν–₯으둜 이동
224
- translation = tf.translation_matrix(direction * 0.2)
225
- original_transform = scene.graph[node_name][0]
226
- new_transform = np.dot(original_transform, translation)
227
- scene.graph[node_name] = new_transform
228
  elif animation_type == 'pulse':
229
- # λͺ¨λΈμ„ μ•½κ°„ 킀움
230
- scale_factor = 1.2
231
-
232
- if isinstance(scene, trimesh.Scene):
233
- # μ”¬μ˜ 쀑심점 계산
234
- all_vertices = []
235
- for geometry_name, geometry in scene.geometry.items():
236
- if hasattr(geometry, 'vertices') and len(geometry.vertices) > 0:
237
- all_vertices.append(geometry.vertices)
238
-
239
- if all_vertices:
240
- all_points = np.vstack(all_vertices)
241
- center = np.mean(all_points, axis=0)
242
-
243
- for node_name, transform, geometry_name in scene.graph.nodes_geometry:
244
- # 쀑심 κΈ°μ€€ μŠ€μΌ€μΌλ§
245
- translate_to_center = tf.translation_matrix(-center)
246
- scale = np.eye(4)
247
- scale[:3, :3] *= scale_factor
248
- translate_back = tf.translation_matrix(center)
249
-
250
- # λ³€ν™˜ 적용
251
- original_transform = scene.graph[node_name][0]
252
- new_transform = np.dot(translate_back, np.dot(scale, np.dot(translate_to_center, original_transform)))
253
- scene.graph[node_name] = new_transform
254
- elif isinstance(scene, trimesh.Trimesh):
255
- # λ©”μ‹œ 쀑심 κΈ°μ€€ μŠ€μΌ€μΌλ§
256
- center = scene.centroid
257
- translate_to_center = tf.translation_matrix(-center)
258
- scale = tf.scale_matrix(scale_factor)
259
- translate_back = tf.translation_matrix(center)
260
- scene.apply_transform(np.dot(translate_back, np.dot(scale, translate_to_center)))
261
- else:
262
- # 기본적으둜 νšŒμ „ 적용
263
- angle = math.pi / 4
264
- axis = [0, 1, 0]
265
 
266
- # νšŒμ „ 적용 (float, explode, pulse μ•„λ‹Œ 경우)
267
- if angle != 0:
268
- if isinstance(scene, trimesh.Scene):
269
- # μ”¬μ˜ λͺ¨λ“  뢀뢄에 νšŒμ „ 적용
270
- for node_name, transform, geometry_name in scene.graph.nodes_geometry:
271
- rotation = tf.rotation_matrix(angle, axis)
272
- original_transform = scene.graph[node_name][0]
273
- new_transform = np.dot(original_transform, rotation)
274
- scene.graph[node_name] = new_transform
275
- elif isinstance(scene, trimesh.Trimesh):
276
- # 단일 λ©”μ‹œμ— νšŒμ „ 적용
277
- rotation = tf.rotation_matrix(angle, axis)
278
- scene.apply_transform(rotation)
279
 
280
- # κ²°κ³Ό μ €μž₯
281
  scene.export(output_glb_path)
282
- print(f"Saved animated GLB to {output_glb_path}")
 
283
  return output_glb_path
 
284
  except Exception as e:
285
- print(f"Error creating animated GLB: {str(e)}")
 
286
  # 였λ₯˜ λ°œμƒ μ‹œ 원본 파일 볡사
287
  try:
288
  import shutil
289
- output_path = os.path.join(LOG_PATH, f"copy_{os.path.basename(input_glb_path)}")
290
- shutil.copy(input_glb_path, output_path)
291
- print(f"Copied original GLB to {output_path}")
292
- return output_path
293
  except Exception as copy_error:
294
  print(f"Error copying GLB: {copy_error}")
295
- return input_glb_path # 원본 경둜 λ°˜ν™˜
296
 
297
  @spaces.GPU
298
  def process_3d_model(input_3d, animation_type, animation_duration, fps):
@@ -300,19 +158,20 @@ def process_3d_model(input_3d, animation_type, animation_duration, fps):
300
  print(f"Processing: {input_3d} with animation type: {animation_type}")
301
 
302
  try:
303
- # 1. μ—…λ‘œλ“œλœ GLB νŒŒμΌμ— μ‹€μ œ μ• λ‹ˆλ©”μ΄μ…˜ 적용
304
- animated_glb_path = create_glb_with_animation(
305
- input_3d,
306
- animation_type,
307
- animation_duration,
308
- fps
309
- )
310
-
311
- # 2. ν…μŠ€νŠΈ 기반 μ• λ‹ˆλ©”μ΄μ…˜ GIF 생성 (λ°±μ—…μš©)
312
  base_filename = os.path.basename(input_3d).rsplit('.', 1)[0]
313
- text_gif_path = os.path.join(LOG_PATH, f'text_animated_{base_filename}.gif')
314
- animated_gif_path = create_textual_animation_gif(
315
- text_gif_path,
 
 
 
 
 
 
 
 
 
316
  os.path.basename(input_3d),
317
  animation_type,
318
  animation_duration,
@@ -320,6 +179,7 @@ def process_3d_model(input_3d, animation_type, animation_duration, fps):
320
  )
321
 
322
  # 3. 메타데이터 생성
 
323
  metadata = {
324
  "animation_type": animation_type,
325
  "duration": animation_duration,
@@ -328,15 +188,28 @@ def process_3d_model(input_3d, animation_type, animation_duration, fps):
328
  "created_at": time.strftime("%Y-%m-%d %H:%M:%S")
329
  }
330
 
331
- json_path = os.path.join(LOG_PATH, f'metadata_{base_filename}.json')
332
  with open(json_path, 'w') as f:
333
  json.dump(metadata, f, indent=4)
334
-
335
- return animated_glb_path, animated_gif_path, json_path
 
 
336
  except Exception as e:
337
- error_msg = f"Error processing file: {str(e)}"
338
- print(error_msg)
339
- return error_msg, None, None
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  # Gradio μΈν„°νŽ˜μ΄μŠ€ μ„€μ •
342
  with gr.Blocks(title="GLB μ• λ‹ˆλ©”μ΄μ…˜ 생성기") as demo:
 
4
  import json
5
  import numpy as np
6
  import trimesh
 
 
7
  from PIL import Image, ImageDraw
8
  import math
9
  import trimesh.transformations as tf
 
17
  LOG_PATH = './results/demo'
18
  os.makedirs(LOG_PATH, exist_ok=True)
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def create_textual_animation_gif(output_path, model_name, animation_type, duration=3.0, fps=30):
21
+ """ν…μŠ€νŠΈ 기반의 κ°„λ‹¨ν•œ μ• λ‹ˆλ©”μ΄μ…˜ GIF 생성"""
22
  try:
 
23
  frames = []
24
  num_frames = int(duration * fps)
25
+ if num_frames > 60:
26
  num_frames = 60
27
 
28
  for i in range(num_frames):
29
+ t = i / (num_frames - 1)
30
+ angle = t * 360
31
 
 
32
  img = Image.new('RGB', (640, 480), color=(240, 240, 240))
33
  draw = ImageDraw.Draw(img)
34
 
 
35
  draw.text((50, 50), f"Model: {os.path.basename(model_name)}", fill=(0, 0, 0))
36
  draw.text((50, 100), f"Animation Type: {animation_type}", fill=(0, 0, 0))
37
  draw.text((50, 150), f"Frame: {i+1}/{num_frames}", fill=(0, 0, 0))
38
 
39
+ # μ• λ‹ˆλ©”μ΄μ…˜ μœ ν˜•λ³„ μ‹œκ°ν™”
40
  center_x, center_y = 320, 240
41
  if animation_type == 'rotate':
 
42
  radius = 100
43
  x = center_x + radius * math.cos(math.radians(angle))
44
  y = center_y + radius * math.sin(math.radians(angle))
45
  draw.rectangle((x-40, y-40, x+40, y+40), outline=(0, 0, 0), fill=(255, 0, 0))
 
46
  elif animation_type == 'float':
 
47
  offset_y = 50 * math.sin(2 * math.pi * t)
48
  draw.ellipse((center_x-50, center_y-50+offset_y, center_x+50, center_y+50+offset_y),
49
+ outline=(0, 0, 0), fill=(0, 0, 255))
50
+ elif animation_type in ['explode', 'assemble']:
 
 
51
  scale = t if animation_type == 'explode' else 1 - t
52
  for j in range(8):
53
  angle_j = j * 45
 
61
  draw.ellipse((x-20, y-20, x+20, y+20), outline=(0, 0, 0), fill=(0, 255, 0))
62
  else:
63
  draw.polygon([(x, y-20), (x+20, y+20), (x-20, y+20)], outline=(0, 0, 0), fill=(0, 0, 255))
 
64
  elif animation_type == 'pulse':
 
65
  scale = 0.5 + 0.5 * math.sin(2 * math.pi * t)
66
  radius = 100 * scale
67
  draw.ellipse((center_x-radius, center_y-radius, center_x+radius, center_y+radius),
68
  outline=(0, 0, 0), fill=(0, 255, 0))
 
69
  elif animation_type == 'swing':
 
70
  angle_offset = 30 * math.sin(2 * math.pi * t)
71
  points = [
72
  (center_x + 100 * math.cos(math.radians(angle_offset)), center_y - 80),
 
75
  ]
76
  draw.polygon(points, outline=(0, 0, 0), fill=(255, 165, 0))
77
 
 
78
  frames.append(img)
79
 
 
80
  frames[0].save(
81
  output_path,
82
  save_all=True,
 
91
  print(f"Error creating textual animation: {str(e)}")
92
  return None
93
 
94
+ def modify_glb_file(input_glb_path, output_glb_path, animation_type='rotate'):
95
+ """μ—…λ‘œλ“œλœ GLB νŒŒμΌμ„ μˆ˜μ •ν•˜μ—¬ μ• λ‹ˆλ©”μ΄μ…˜ 효과λ₯Ό μ£ΌλŠ” ν•¨μˆ˜"""
 
 
96
  try:
97
+ # κ°„λ‹¨ν•œ 방법: 원본 νŒŒμΌμ„ κ·ΈλŒ€λ‘œ λ‘œλ“œν•˜μ—¬ 단일 λ³€ν™˜ 적용 ν›„ μ €μž₯
98
+ # μ—¬λŸ¬ λ‹¨κ³„λ‘œ λ‚˜λˆ„μ–΄ μ²˜λ¦¬ν•˜μ—¬ 각 λ‹¨κ³„μ—μ„œ 였λ₯˜λ₯Ό 확인할 수 μžˆλ„λ‘ 함
99
 
100
+ print(f"Step 1: Loading GLB file '{input_glb_path}'")
101
  scene = trimesh.load(input_glb_path)
102
+ print(f"Loaded GLB file, type: {type(scene)}")
103
+
104
+ print(f"Step 2: Preparing transformation for animation type: {animation_type}")
105
+ # λ‹¨μˆœν™”λœ λ³€ν™˜ μ€€λΉ„ - μ• λ‹ˆλ©”μ΄μ…˜ μœ ν˜•λ³„λ‘œ λ‹€λ₯Έ λ³€ν™˜ 적용
106
+ transform = np.eye(4) # κΈ°λ³Έ ν•­λ“± λ³€ν™˜ (아무 λ³€ν™” μ—†μŒ)
107
 
 
108
  if animation_type == 'rotate':
109
+ # YμΆ• κΈ°μ€€ 45도 νšŒμ „
110
+ transform = tf.rotation_matrix(math.pi/4, [0, 1, 0])
 
111
  elif animation_type == 'float':
112
+ # μœ„λ‘œ 이동
113
+ transform = tf.translation_matrix([0, 0.5, 0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  elif animation_type == 'pulse':
115
+ # 크기 ν™•λŒ€
116
+ transform = tf.scale_matrix(1.2)
117
+ elif animation_type == 'explode':
118
+ # XμΆ• λ°©ν–₯으둜 μ•½κ°„ 이동
119
+ transform = tf.translation_matrix([0.5, 0, 0])
120
+ elif animation_type == 'assemble':
121
+ # XμΆ• λ°©ν–₯으둜 μ•½κ°„ 이동 (λ°˜λŒ€ λ°©ν–₯)
122
+ transform = tf.translation_matrix([-0.5, 0, 0])
123
+ elif animation_type == 'swing':
124
+ # ZμΆ• κΈ°μ€€ μ•½κ°„ νšŒμ „
125
+ transform = tf.rotation_matrix(math.pi/8, [0, 0, 1])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ print(f"Step 3: Applying transformation to scene")
128
+ if isinstance(scene, trimesh.Scene):
129
+ # Scene인 경우 직접 λ³€ν™˜ 적용
130
+ scene.apply_transform(transform)
131
+ print(f"Applied transform to scene")
132
+ else:
133
+ print(f"Scene is not trimesh.Scene, but {type(scene)}")
 
 
 
 
 
 
134
 
135
+ print(f"Step 4: Exporting modified scene to '{output_glb_path}'")
136
  scene.export(output_glb_path)
137
+ print(f"Successfully exported modified GLB to '{output_glb_path}'")
138
+
139
  return output_glb_path
140
+
141
  except Exception as e:
142
+ print(f"Error modifying GLB file: {str(e)}")
143
+
144
  # 였λ₯˜ λ°œμƒ μ‹œ 원본 파일 볡사
145
  try:
146
  import shutil
147
+ print(f"Copying original GLB file as fallback")
148
+ shutil.copy(input_glb_path, output_glb_path)
149
+ print(f"Successfully copied original GLB to '{output_glb_path}'")
150
+ return output_glb_path
151
  except Exception as copy_error:
152
  print(f"Error copying GLB: {copy_error}")
153
+ return input_glb_path # 원본 파일 경둜 λ°˜ν™˜
154
 
155
  @spaces.GPU
156
  def process_3d_model(input_3d, animation_type, animation_duration, fps):
 
158
  print(f"Processing: {input_3d} with animation type: {animation_type}")
159
 
160
  try:
161
+ # 파일λͺ… μ€€λΉ„
 
 
 
 
 
 
 
 
162
  base_filename = os.path.basename(input_3d).rsplit('.', 1)[0]
163
+ animated_glb_path = os.path.join(LOG_PATH, f'animated_{base_filename}.glb')
164
+ animated_gif_path = os.path.join(LOG_PATH, f'text_animated_{base_filename}.gif')
165
+ json_path = os.path.join(LOG_PATH, f'metadata_{base_filename}.json')
166
+
167
+ # 1. GLB 파일 μˆ˜μ •
168
+ print(f"Modifying GLB file")
169
+ modified_glb = modify_glb_file(input_3d, animated_glb_path, animation_type)
170
+
171
+ # 2. μ• λ‹ˆλ©”μ΄μ…˜ GIF 생성 (μ–΄λ–€ κ²½μš°μ—λ„ 항상 생성)
172
+ print(f"Creating animation GIF")
173
+ animated_gif = create_textual_animation_gif(
174
+ animated_gif_path,
175
  os.path.basename(input_3d),
176
  animation_type,
177
  animation_duration,
 
179
  )
180
 
181
  # 3. 메타데이터 생성
182
+ print(f"Creating metadata")
183
  metadata = {
184
  "animation_type": animation_type,
185
  "duration": animation_duration,
 
188
  "created_at": time.strftime("%Y-%m-%d %H:%M:%S")
189
  }
190
 
 
191
  with open(json_path, 'w') as f:
192
  json.dump(metadata, f, indent=4)
193
+
194
+ print(f"Processing complete, returning results")
195
+ return modified_glb, animated_gif, json_path
196
+
197
  except Exception as e:
198
+ print(f"Error in process_3d_model: {str(e)}")
199
+ # μ‹¬κ°ν•œ 였λ₯˜ λ°œμƒ μ‹œ 원본 파일과 κΈ°λ³Έ GIF λ°˜ν™˜
200
+ try:
201
+ base_filename = os.path.basename(input_3d).rsplit('.', 1)[0]
202
+ animated_gif_path = os.path.join(LOG_PATH, f'text_animated_{base_filename}.gif')
203
+ create_textual_animation_gif(
204
+ animated_gif_path,
205
+ os.path.basename(input_3d),
206
+ animation_type,
207
+ animation_duration,
208
+ fps
209
+ )
210
+ return input_3d, animated_gif_path, None
211
+ except:
212
+ return f"Error processing file: {str(e)}", None, None
213
 
214
  # Gradio μΈν„°νŽ˜μ΄μŠ€ μ„€μ •
215
  with gr.Blocks(title="GLB μ• λ‹ˆλ©”μ΄μ…˜ 생성기") as demo: