Export_3ds: Added distance cue chunk export
[blender-addons.git] / measureit / measureit_render.py
blob55fa6084580bbd46fcf5295b5e2f8fc129974818
1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # ----------------------------------------------------------
6 # support routines for render measures in final image
7 # Author: Antonio Vazquez (antonioya)
9 # ----------------------------------------------------------
10 # noinspection PyUnresolvedReferences
11 import bpy
12 import gpu
13 # noinspection PyUnresolvedReferences
14 import blf
15 from os import path, remove
16 from sys import exc_info
17 # noinspection PyUnresolvedReferences
18 import bpy_extras.image_utils as img_utils
19 # noinspection PyUnresolvedReferences
20 import bpy_extras.object_utils as object_utils
21 # noinspection PyUnresolvedReferences
22 from bpy_extras import view3d_utils
23 from math import ceil
24 from .measureit_geometry import *
27 # -------------------------------------------------------------
28 # Render image main entry point
30 # -------------------------------------------------------------
31 def render_main(self, context, animation=False):
32 # Save old info
33 settings = bpy.context.scene.render.image_settings
34 depth = settings.color_depth
35 settings.color_depth = '8'
37 # Get object list
38 scene = context.scene
39 objlist = context.scene.objects
40 # --------------------
41 # Get resolution
42 # --------------------
43 render_scale = scene.render.resolution_percentage / 100
44 width = int(scene.render.resolution_x * render_scale)
45 height = int(scene.render.resolution_y * render_scale)
47 # --------------------------------------
48 # Loop to draw all lines in Offsecreen
49 # --------------------------------------
50 offscreen = gpu.types.GPUOffScreen(width, height)
51 view_matrix = Matrix([
52 [2 / width, 0, 0, -1],
53 [0, 2 / height, 0, -1],
54 [0, 0, 1, 0],
55 [0, 0, 0, 1]])
57 with offscreen.bind():
58 fb = gpu.state.active_framebuffer_get()
59 fb.clear(color=(0.0, 0.0, 0.0, 0.0))
60 gpu.matrix.reset()
61 gpu.matrix.load_matrix(view_matrix)
62 gpu.matrix.load_projection_matrix(Matrix.Identity(4))
64 # -----------------------------
65 # Loop to draw all objects
66 # -----------------------------
67 for myobj in objlist:
68 if myobj.visible_get() is True:
69 if 'MeasureGenerator' in myobj:
70 op = myobj.MeasureGenerator[0]
71 draw_segments(context, myobj, op, None, None)
72 # -----------------------------
73 # Loop to draw all debug
74 # -----------------------------
75 if scene.measureit_debug is True:
76 selobj = bpy.context.selected_objects
77 for myobj in selobj:
78 if scene.measureit_debug_objects is True:
79 draw_object(context, myobj, None, None)
80 elif scene.measureit_debug_object_loc is True:
81 draw_object(context, myobj, None, None)
82 if scene.measureit_debug_vertices is True:
83 draw_vertices(context, myobj, None, None)
84 elif scene.measureit_debug_vert_loc is True:
85 draw_vertices(context, myobj, None, None)
86 if scene.measureit_debug_edges is True:
87 draw_edges(context, myobj, None, None)
88 if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True:
89 draw_faces(context, myobj, None, None)
90 # -----------------------------
91 # Draw a rectangle frame
92 # -----------------------------
93 if scene.measureit_rf is True:
94 rfcolor = scene.measureit_rf_color
95 rfborder = scene.measureit_rf_border
96 rfline = scene.measureit_rf_line
98 imm_set_line_width(rfline)
99 x1 = rfborder
100 x2 = width - rfborder
101 y1 = int(ceil(rfborder / (width / height)))
102 y2 = height - y1
103 draw_rectangle((x1, y1), (x2, y2), rfcolor)
105 buffer = fb.read_color(0, 0, width, height, 4, 0, 'UBYTE')
106 buffer.dimensions = width * height * 4
108 offscreen.free()
110 # -----------------------------
111 # Create image
112 # -----------------------------
113 image_name = "measureit_output"
114 if not image_name in bpy.data.images:
115 bpy.data.images.new(image_name, width, height)
117 image = bpy.data.images[image_name]
118 image.scale(width, height)
119 image.pixels = [v / 255 for v in buffer]
121 # Saves image
122 if image is not None and (scene.measureit_render is True or animation is True):
123 ren_path = bpy.context.scene.render.filepath
124 filename = "mit_frame"
125 if len(ren_path) > 0:
126 if ren_path.endswith(path.sep):
127 initpath = path.realpath(ren_path) + path.sep
128 else:
129 (initpath, filename) = path.split(ren_path)
131 ftxt = "%04d" % scene.frame_current
132 outpath = path.realpath(path.join(initpath, filename + ftxt + ".png"))
133 save_image(self, outpath, image)
135 # restore default value
136 settings.color_depth = depth
139 # -------------------------------------
140 # Save image to file
141 # -------------------------------------
142 def save_image(self, filepath, myimage):
143 # noinspection PyBroadException
144 try:
146 # Save old info
147 settings = bpy.context.scene.render.image_settings
148 myformat = settings.file_format
149 mode = settings.color_mode
150 depth = settings.color_depth
152 # Apply new info and save
153 settings.file_format = 'PNG'
154 settings.color_mode = "RGBA"
155 settings.color_depth = '8'
156 myimage.save_render(filepath)
157 print("MeasureIt: Image " + filepath + " saved")
159 # Restore old info
160 settings.file_format = myformat
161 settings.color_mode = mode
162 settings.color_depth = depth
163 except:
164 print("Unexpected error:" + str(exc_info()))
165 self.report({'ERROR'}, "MeasureIt: Unable to save render image")
166 return