diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2016-08-03 03:47:46 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2016-08-03 03:47:46 +0300 |
commit | cf4ac00ea0aabfbc1c84b085c53991862003f5ae (patch) | |
tree | 6f145d6cb875e314ee2f2672d213b36087641927 /measureit/measureit_render.py | |
parent | 5cd9040c995effc4c6bf233e820f741cbaf083ca (diff) |
add mesureit to release "warning temporary status" pending T48704
Diffstat (limited to 'measureit/measureit_render.py')
-rw-r--r-- | measureit/measureit_render.py | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/measureit/measureit_render.py b/measureit/measureit_render.py new file mode 100644 index 00000000..6c9733df --- /dev/null +++ b/measureit/measureit_render.py @@ -0,0 +1,343 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +# ---------------------------------------------------------- +# support routines for render measures in final image +# Author: Antonio Vazquez (antonioya) +# +# ---------------------------------------------------------- +# noinspection PyUnresolvedReferences +import bpy +# noinspection PyUnresolvedReferences +import bgl +# noinspection PyUnresolvedReferences +import blf +# noinspection PyUnresolvedReferences +import mathutils +# noinspection PyUnresolvedReferences +import bmesh +import os +import sys +# noinspection PyUnresolvedReferences +import bpy_extras.image_utils as img_utils +# noinspection PyUnresolvedReferences +import bpy_extras.object_utils as object_utils +# noinspection PyUnresolvedReferences +from bpy_extras import view3d_utils +from math import ceil +from measureit_geometry import * + + +# ------------------------------------------------------------- +# Render image main entry point +# +# ------------------------------------------------------------- +def render_main(self, context, animation=False): + # noinspection PyBroadException,PyBroadException + # Save old info + settings = bpy.context.scene.render.image_settings + depth = settings.color_depth + settings.color_depth = '8' + # noinspection PyBroadException + try: + # Get visible layers + layers = [] + scene = context.scene + for x in range(0, 20): + if scene.layers[x] is True: + layers.extend([x]) + + # Get object list + objlist = context.scene.objects + # -------------------- + # Get resolution + # -------------------- + scene = bpy.context.scene + render_scale = scene.render.resolution_percentage / 100 + + width = int(scene.render.resolution_x * render_scale) + height = int(scene.render.resolution_y * render_scale) + # --------------------------------------- + # Get output path + # --------------------------------------- + ren_path = bpy.context.scene.render.filepath + if len(ren_path) > 0: + if ren_path.endswith(os.path.sep): + initpath = os.path.realpath(ren_path) + os.path.sep + else: + (initpath, filename) = os.path.split(ren_path) + outpath = os.path.join(initpath, "measureit_tmp_render.png") + else: + self.report({'ERROR'}, + "MeasureIt: Unable to save temporary render image. Define a valid render path") + settings.color_depth = depth + return False + + # Get Render Image + img = get_render_image(outpath) + if img is None: + self.report({'ERROR'}, + "MeasureIt: Unable to save temporary render image. Define a valid render path") + settings.color_depth = depth + return False + + # ----------------------------- + # Calculate rows and columns + # ----------------------------- + tile_x = 240 + tile_y = 216 + row_num = ceil(height / tile_y) + col_num = ceil(width / tile_x) + print("MeasureIt: Image divided in " + str(row_num) + "x" + str(col_num) + " tiles") + + # pixels out of visible area + cut4 = (col_num * tile_x * 4) - width * 4 # pixels aout of drawing area + totpixel4 = width * height * 4 # total pixels RGBA + + viewport_info = bgl.Buffer(bgl.GL_INT, 4) + bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) + + # Load image on memory + img.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST) + + # 2.77 API change + if bpy.app.version >= (2, 77, 0): + tex = img.bindcode[0] + else: + tex = img.bindcode + + # -------------------------------------------- + # Create output image (to apply texture) + # -------------------------------------------- + if "measureit_output" in bpy.data.images: + out_img = bpy.data.images["measureit_output"] + if out_img is not None: + out_img.user_clear() + bpy.data.images.remove(out_img) + + out = bpy.data.images.new("measureit_output", width, height) + tmp_pixels = [1] * totpixel4 + + # -------------------------------- + # Loop for all tiles + # -------------------------------- + for row in range(0, row_num): + for col in range(0, col_num): + buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) + bgl.glDisable(bgl.GL_SCISSOR_TEST) # if remove this line, get blender screenshot not image + bgl.glViewport(0, 0, tile_x, tile_y) + + bgl.glMatrixMode(bgl.GL_PROJECTION) + bgl.glLoadIdentity() + + # defines ortographic view for single tile + x1 = tile_x * col + y1 = tile_y * row + bgl.gluOrtho2D(x1, x1 + tile_x, y1, y1 + tile_y) + + # Clear + bgl.glClearColor(0.0, 0.0, 0.0, 0.0) + bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) + + bgl.glEnable(bgl.GL_TEXTURE_2D) + bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) + + # defines drawing area + bgl.glBegin(bgl.GL_QUADS) + + bgl.glColor3f(1.0, 1.0, 1.0) + bgl.glTexCoord2f(0.0, 0.0) + bgl.glVertex2f(0.0, 0.0) + + bgl.glTexCoord2f(1.0, 0.0) + bgl.glVertex2f(width, 0.0) + + bgl.glTexCoord2f(1.0, 1.0) + bgl.glVertex2f(width, height) + + bgl.glTexCoord2f(0.0, 1.0) + bgl.glVertex2f(0.0, height) + + bgl.glEnd() + + # ----------------------------- + # Loop to draw all lines + # ----------------------------- + for myobj in objlist: + if myobj.hide is False: + if 'MeasureGenerator' in myobj: + # verify visible layer + for x in range(0, 20): + if myobj.layers[x] is True: + if x in layers: + op = myobj.MeasureGenerator[0] + draw_segments(context, myobj, op, None, None) + break + + # ----------------------------- + # Loop to draw all debug + # ----------------------------- + if scene.measureit_debug is True: + selobj = bpy.context.selected_objects + for myobj in selobj: + if scene.measureit_debug_vertices is True: + draw_vertices(context, myobj, None, None) + if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True: + draw_faces(context, myobj, None, None) + + if scene.measureit_rf is True: + bgl.glColor3f(1.0, 1.0, 1.0) + rfcolor = scene.measureit_rf_color + rfborder = scene.measureit_rf_border + rfline = scene.measureit_rf_line + + bgl.glLineWidth(rfline) + bgl.glColor4f(rfcolor[0], rfcolor[1], rfcolor[2], rfcolor[3]) + + x1 = rfborder + x2 = width - rfborder + y1 = int(math.ceil(rfborder / (width / height))) + y2 = height - y1 + draw_rectangle((x1, y1), (x2, y2)) + + # -------------------------------- + # copy pixels to temporary area + # -------------------------------- + bgl.glFinish() + bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # read image data + for y in range(0, tile_y): + # final image pixels position + p1 = (y * width * 4) + (row * tile_y * width * 4) + (col * tile_x * 4) + p2 = p1 + (tile_x * 4) + # buffer pixels position + b1 = y * width * 4 + b2 = b1 + (tile_x * 4) + + if p1 < totpixel4: # avoid pixel row out of area + if col == col_num - 1: # avoid pixel columns out of area + p2 -= cut4 + b2 -= cut4 + + tmp_pixels[p1:p2] = buffer[b1:b2] + + # ----------------------- + # Copy temporary to final + # ----------------------- + out.pixels = tmp_pixels[:] # Assign image data + img.gl_free() # free opengl image memory + + # delete image + img.user_clear() + bpy.data.images.remove(img) + # remove temp file + os.remove(outpath) + # reset + bgl.glEnable(bgl.GL_SCISSOR_TEST) + # ----------------------- + # restore opengl defaults + # ----------------------- + bgl.glLineWidth(1) + bgl.glDisable(bgl.GL_BLEND) + bgl.glColor4f(0.0, 0.0, 0.0, 1.0) + # Saves image + if out is not None and (scene.measureit_render is True or animation is True): + ren_path = bpy.context.scene.render.filepath + filename = "mit_frame" + if len(ren_path) > 0: + if ren_path.endswith(os.path.sep): + initpath = os.path.realpath(ren_path) + os.path.sep + else: + (initpath, filename) = os.path.split(ren_path) + + ftxt = "%04d" % scene.frame_current + outpath = os.path.join(initpath, filename + ftxt + ".png") + + save_image(self, outpath, out) + + settings.color_depth = depth + return True + + except: + settings.color_depth = depth + print("Unexpected error:" + str(sys.exc_info())) + self.report({'ERROR'}, "MeasureIt: Unable to create render image") + return False + + +# -------------------------------------------------------------------- +# Get the final render image and return as image object +# +# return None if no render available +# -------------------------------------------------------------------- +def get_render_image(outpath): + saved = False + # noinspection PyBroadException + try: + # noinspection PyBroadException + try: + result = bpy.data.images['Render Result'] + if result.has_data is False: + # this save produce to fill data image + result.save_render(outpath) + saved = True + except: + print("No render image found") + return None + + # Save and reload + if saved is False: + result.save_render(outpath) + + img = img_utils.load_image(outpath) + + return img + except: + print("Unexpected render image error") + return None + + +# ------------------------------------- +# Save image to file +# ------------------------------------- +def save_image(self, filepath, myimage): + # noinspection PyBroadException + try: + + # Save old info + settings = bpy.context.scene.render.image_settings + myformat = settings.file_format + mode = settings.color_mode + depth = settings.color_depth + + # Apply new info and save + settings.file_format = 'PNG' + settings.color_mode = "RGBA" + settings.color_depth = '8' + myimage.save_render(filepath) + print("MeasureIt: Image " + filepath + " saved") + + # Restore old info + settings.file_format = myformat + settings.color_mode = mode + settings.color_depth = depth + except: + print("Unexpected error:" + str(sys.exc_info())) + self.report({'ERROR'}, "MeasureIt: Unable to save render image") + return |