165 lines
5.8 KiB
Python
165 lines
5.8 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# ----------------------------------------------------------
|
|
# support routines for render measures in final image
|
|
# Author: Antonio Vazquez (antonioya)
|
|
#
|
|
# ----------------------------------------------------------
|
|
# noinspection PyUnresolvedReferences
|
|
import bpy
|
|
import gpu
|
|
# noinspection PyUnresolvedReferences
|
|
import blf
|
|
from os import path, remove
|
|
from sys import exc_info
|
|
# 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):
|
|
# Save old info
|
|
settings = bpy.context.scene.render.image_settings
|
|
depth = settings.color_depth
|
|
settings.color_depth = '8'
|
|
|
|
# Get object list
|
|
scene = context.scene
|
|
objlist = context.scene.objects
|
|
# --------------------
|
|
# Get resolution
|
|
# --------------------
|
|
render_scale = scene.render.resolution_percentage / 100
|
|
width = int(scene.render.resolution_x * render_scale)
|
|
height = int(scene.render.resolution_y * render_scale)
|
|
|
|
# --------------------------------------
|
|
# Loop to draw all lines in Offsecreen
|
|
# --------------------------------------
|
|
offscreen = gpu.types.GPUOffScreen(width, height)
|
|
view_matrix = Matrix([
|
|
[2 / width, 0, 0, -1],
|
|
[0, 2 / height, 0, -1],
|
|
[0, 0, 1, 0],
|
|
[0, 0, 0, 1]])
|
|
|
|
with offscreen.bind():
|
|
fb = gpu.state.active_framebuffer_get()
|
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
|
gpu.matrix.reset()
|
|
gpu.matrix.load_matrix(view_matrix)
|
|
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
|
|
|
# -----------------------------
|
|
# Loop to draw all objects
|
|
# -----------------------------
|
|
for myobj in objlist:
|
|
if myobj.visible_get() is True:
|
|
if 'MeasureGenerator' in myobj:
|
|
op = myobj.MeasureGenerator[0]
|
|
draw_segments(context, myobj, op, None, None)
|
|
# -----------------------------
|
|
# Loop to draw all debug
|
|
# -----------------------------
|
|
if scene.measureit_debug is True:
|
|
selobj = bpy.context.selected_objects
|
|
for myobj in selobj:
|
|
if scene.measureit_debug_objects is True:
|
|
draw_object(context, myobj, None, None)
|
|
elif scene.measureit_debug_object_loc is True:
|
|
draw_object(context, myobj, None, None)
|
|
if scene.measureit_debug_vertices is True:
|
|
draw_vertices(context, myobj, None, None)
|
|
elif scene.measureit_debug_vert_loc is True:
|
|
draw_vertices(context, myobj, None, None)
|
|
if scene.measureit_debug_edges is True:
|
|
draw_edges(context, myobj, None, None)
|
|
if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True:
|
|
draw_faces(context, myobj, None, None)
|
|
# -----------------------------
|
|
# Draw a rectangle frame
|
|
# -----------------------------
|
|
if scene.measureit_rf is True:
|
|
rfcolor = scene.measureit_rf_color
|
|
rfborder = scene.measureit_rf_border
|
|
rfline = scene.measureit_rf_line
|
|
|
|
imm_set_line_width(rfline)
|
|
x1 = rfborder
|
|
x2 = width - rfborder
|
|
y1 = int(ceil(rfborder / (width / height)))
|
|
y2 = height - y1
|
|
draw_rectangle((x1, y1), (x2, y2), rfcolor)
|
|
|
|
buffer = fb.read_color(0, 0, width, height, 4, 0, 'UBYTE')
|
|
buffer.dimensions = width * height * 4
|
|
|
|
offscreen.free()
|
|
|
|
# -----------------------------
|
|
# Create image
|
|
# -----------------------------
|
|
image_name = "measureit_output"
|
|
if not image_name in bpy.data.images:
|
|
bpy.data.images.new(image_name, width, height)
|
|
|
|
image = bpy.data.images[image_name]
|
|
image.scale(width, height)
|
|
image.pixels = [v / 255 for v in buffer]
|
|
|
|
# Saves image
|
|
if image 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(path.sep):
|
|
initpath = path.realpath(ren_path) + path.sep
|
|
else:
|
|
(initpath, filename) = path.split(ren_path)
|
|
|
|
ftxt = "%04d" % scene.frame_current
|
|
outpath = path.realpath(path.join(initpath, filename + ftxt + ".png"))
|
|
save_image(self, outpath, image)
|
|
|
|
# restore default value
|
|
settings.color_depth = depth
|
|
|
|
|
|
# -------------------------------------
|
|
# 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(exc_info()))
|
|
self.report({'ERROR'}, "MeasureIt: Unable to save render image")
|
|
return
|