Updated the template for viewing stl models.
[mediagoblin.git] / mediagoblin / media_types / stl / processing.py
CommitLineData
76918e52
AN
1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import os
12a10467 18import json
76918e52 19import logging
12a10467 20import subprocess
76918e52
AN
21
22from mediagoblin import mg_globals as mgg
23from mediagoblin.processing import create_pub_filepath, \
24 FilenameBuilder
25
26from mediagoblin.media_types.stl import model_loader
27
28
29_log = logging.getLogger(__name__)
30SUPPORTED_FILETYPES = ['stl', 'obj']
31
32
33def sniff_handler(media_file, **kw):
34 if kw.get('media') is not None:
35 name, ext = os.path.splitext(kw['media'].filename)
36 clean_ext = ext[1:].lower()
37
38 if clean_ext in SUPPORTED_FILETYPES:
39 _log.info('Found file extension in supported filetypes')
40 return True
41 else:
42 _log.debug('Media present, extension not found in {0}'.format(
43 SUPPORTED_FILETYPES))
44 else:
45 _log.warning('Need additional information (keyword argument \'media\')'
46 ' to be able to handle sniffing')
47
48 return False
49
50
12a10467
AN
51def blender_render(config):
52 """
53 Called to prerender a model.
54 """
55 arg_string = "blender -b blender_render.blend -F "
56 arg_string +="JPEG -P blender_render.py"
57 env = {"RENDER_SETUP" : json.dumps(config), "DISPLAY":":0"}
58 subprocess.call(arg_string.split(" "), env=env)
59
60
76918e52
AN
61def process_stl(entry):
62 """
63 Code to process an stl or obj model.
64 """
65
66 workbench = mgg.workbench_manager.create_workbench()
67 # Conversions subdirectory to avoid collisions
68 conversions_subdir = os.path.join(
69 workbench.dir, 'conversions')
70 os.mkdir(conversions_subdir)
71 queued_filepath = entry.queued_media_file
72 queued_filename = workbench.localized_file(
73 mgg.queue_store, queued_filepath, 'source')
74 name_builder = FilenameBuilder(queued_filename)
75
76 ext = queued_filename.lower().strip()[-4:]
77 if ext.startswith("."):
78 ext = ext[1:]
79 else:
80 ext = None
81
82 # Attempt to parse the model file and divine some useful
83 # information about it.
84 with open(queued_filename, 'rb') as model_file:
85 model = model_loader.auto_detect(model_file, ext)
86
12a10467
AN
87 # generate preview images
88 greatest = [model.width, model.height, model.depth]
89 greatest.sort()
90 greatest = greatest[-1]
91
92 def snap(name, camera, width=640, height=640, project="ORTHO"):
93 path = create_pub_filepath(entry, name_builder.fill(name))
94 render_file = mgg.public_store.get_file(path, "wb")
95 shot = {
96 "model_path" : queued_filename,
97 "model_ext" : ext,
98 "camera_coord" : camera,
99 "camera_focus" : model.average,
100 "camera_clip" : greatest*10,
101 "greatest" : greatest,
102 "projection" : project,
103 "width" : width,
104 "height" : height,
105 "out_file" : render_file.name,
106 }
107 render_file.close()
108 blender_render(shot)
109 return path
110
111 thumb_path = snap(
112 "{basename}.thumb.jpg",
113 [0, greatest*-1.5, greatest],
114 mgg.global_config['media:thumb']['max_width'],
115 mgg.global_config['media:thumb']['max_height'],
116 project="PERSP")
117
118 perspective_path = snap(
119 "{basename}.perspective.jpg",
120 [0, greatest*-1.5, greatest], project="PERSP")
121
122 topview_path = snap(
123 "{basename}.top.jpg",
124 [model.average[0], model.average[1], greatest*2])
125
126 frontview_path = snap(
127 "{basename}.front.jpg",
128 [model.average[0], greatest*-2, model.average[2]])
129
130 sideview_path = snap(
131 "{basename}.side.jpg",
132 [greatest*-2, model.average[1], model.average[2]])
133
134
135
76918e52
AN
136
137 # Save the public file stuffs
138 model_filepath = create_pub_filepath(
139 entry, name_builder.fill('{basename}{ext}'))
140
141 with mgg.public_store.get_file(model_filepath, 'wb') as model_file:
142 with open(queued_filename, 'rb') as queued_file:
143 model_file.write(queued_file.read())
144
145
146 # Remove queued media file from storage and database
147 mgg.queue_store.delete_file(queued_filepath)
148 entry.queued_media_file = []
149
150 # Insert media file information into database
151 media_files_dict = entry.setdefault('media_files', {})
152 media_files_dict[u'original'] = model_filepath
12a10467
AN
153 media_files_dict[u'thumb'] = thumb_path
154 media_files_dict[u'perspective'] = perspective_path
155 media_files_dict[u'top'] = topview_path
156 media_files_dict[u'side'] = sideview_path
157 media_files_dict[u'front'] = frontview_path
76918e52
AN
158
159 # Put model dimensions into the database
160 dimensions = {
161 "center_x" : model.average[0],
162 "center_y" : model.average[1],
163 "center_z" : model.average[2],
164 "width" : model.width,
165 "height" : model.height,
166 "depth" : model.depth,
167 }
168 entry.media_data_init(**dimensions)
169
170 # clean up workbench
171 workbench.destroy_self()