Vue 3D - Comment afficher les données de la caméra dans le cadre de la caméra?
Existe-t-il un moyen d'utiliser des options d'affichage telles que "info d'objet" ou "nom de vue" (dans les préférences de la fenêtre) pour afficher d'autres informations comme par exemple la focale de la caméra active et sa position. Et existe-t-il un moyen de déplacer ces informations n'importe où dans la fenêtre 3D? Comme dans cet exemple:
J'ai donc trouvé un script qui me permet d'afficher le point focal sur la fenêtre 3D.
import bpy
import blf
dns = bpy.app.driver_namespace
dc = dns.get("dc")
dc.remove_handle()
class DrawingClass:
def __init__(self, context, prop):
self.prop = prop
self.handle = bpy.types.SpaceView3D.draw_handler_add(
self.draw_text_callback,(context,),
'WINDOW', 'POST_PIXEL')
def draw_text_callback(self, context):
font_id = 0 # XXX, need to find out how best to get this.
# draw some text
blf.position(font_id, 15, 350, 0)
blf.size(font_id, 20, 72)
blf.draw(font_id, "%s %s" % (context.scene.name, self.prop))
def remove_handle(self):
bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')
context = bpy.context
dns = bpy.app.driver_namespace
dns["dc"] = DrawingClass(context, bpy.context.object.data.lens)
Les 3 premières lignes me permettent d'effacer l'affichage précédent. Comment puis-je empêcher le scipte de lire les 3 premières lignes la première fois que le script est exécuté? Pour l'instant, le script lit une fois la focale et l'écrit. Comment s'assurer que le script est lu à chaque fois que la focale est modifiée?
Réponses
AFAIK ce n'est pas possible par défaut et je suppose qu'il n'y a pas de module complémentaire capable d'afficher tout type d'informations dans le cadre de la caméra.
Cependant, vous pouvez dessiner le texte en utilisant le module bgl de python et créer votre propre add-on. L'exemple de code suivant est basé sur notre célèbre modèle Operator Modal Draw fourni avec le mélangeur, étendu par les réponses des coordonnées des coins de la bordure de la vue de la caméra et du texte multiligne en blf (avec option multicolore) pour faire avancer les choses :
hud.py
import bpy
import blf
import bgl
# -> BASED ON: https://blender.stackexchange.com/a/14746/31447
def view3d_find(context):
# returns first 3d view, normally we get from context
for area in context.window.screen.areas:
if area.type == 'VIEW_3D':
v3d = area.spaces[0]
rv3d = v3d.region_3d
for region in area.regions:
if region.type == 'WINDOW':
return region, rv3d
return None, None
def view3d_camera_border(context):
obj = context.scene.camera
cam = obj.data
frame = cam.view_frame(scene=context.scene)
# move from object-space into world-space
frame = [obj.matrix_world @ v for v in frame]
# move into pixelspace
from bpy_extras.view3d_utils import location_3d_to_region_2d
region, rv3d = view3d_find(context)
frame_px = [location_3d_to_region_2d(region, rv3d, v) for v in frame]
return frame_px
# -> BASED ON: https://blender.stackexchange.com/a/31799/31447
def draw_string(x, y, packed_strings):
font_id = 0
blf.size(font_id, 18, 72)
x_offset = 0
y_offset = 0
line_height = (blf.dimensions(font_id, "M")[1] * 1.45)
for command in packed_strings:
if len(command) == 2:
pstr, pcol = command
blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # #bgl.glColor4f(pcol)
text_width, text_height = blf.dimensions(font_id, pstr)
blf.position(font_id, (x + x_offset), (y + y_offset), 0)
blf.draw(font_id, pstr)
x_offset += text_width
else:
x_offset = 0
y_offset -= line_height
def draw_callback_px(self, context):
WHITE = (1, 1, 1, .7)
CR = "Carriage Return"
x, y = view3d_camera_border(context)[3]
cam_ob = context.scene.camera
if cam_ob is not None:
ps = [
("{} {}mm".format(cam_ob.name, cam_ob.data.lens), WHITE),
CR,
CR,
("T: {:.2f}, {:.2f}, {:.2f}".format(
cam_ob.location.x,
cam_ob.location.y,
cam_ob.location.z), WHITE),
CR,
("R: {:.2f}, {:.2f}, {:.2f}".format(
cam_ob.rotation_euler.x,
cam_ob.rotation_euler.y,
cam_ob.rotation_euler.z), WHITE),
]
draw_string(x+10, y-20, ps)
# restore opengl defaults
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
# -> MODAL OPERATOR TEMPLATE
class ModalDrawOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
bl_idname = "view3d.modal_operator"
bl_label = "Simple Modal View3D Operator"
@classmethod
def poll(cls, context):
return context.area.type == 'VIEW_3D'
def modal(self, context, event):
context.area.tag_redraw()
if event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'PASS_THROUGH'}
def invoke(self, context, event):
if context.space_data.region_3d.view_perspective == 'CAMERA':
# the arguments we pass the the callback
args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "Switch into Camera View")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(ModalDrawOperator)
if __name__ == "__main__":
register()
Copiez et collez le script dans l'éditeur de texte, exécutez-le, passez à la vue 3D, appuyez sur F3et tapez "Opérateur simple ..." pour l'exécuter. Si vous souhaitez le convertir en add-on, ajoutez simplement un dictionnaire python nommé "bl_info" en haut de votre addon:https://wiki.blender.org/wiki/Process/Addons/Guidelines/metainfo
Pour que cela fonctionne pour les versions 2.7x, vous devrez remplacer 2 lignes en raison des modifications apportées à la multiplication matricielle et de la façon de définir la couleur du texte à l'aide de blf.color dans les versions plus récentes:
# draw_string()
- blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # Blender 2.8x
+ bgl.glColor4f(*pcol) # Blender 2.7x
# view3d_camera_border()
- frame = [obj.matrix_world @ v for v in frame] # Blender 2.8x
+ frame = [obj.matrix_world * v for v in frame] # Blender 2.7x