Jour 015 : Trouver la position d’un objet dans une image

Obtenir la position d’un vertex dans une image (position en pixels)

Si je fais la carte avec Blender, j’ai besoin de pouvoir determiner où sont les objets dans le rendu fini. En d’autres termes, j’ai besoin d’avoir une position x,y en pixels à partir des mes objets qui ont une position x,y,z en mètres.

C’est un facteur essentiel de la faisabilité de la méthode que j’ai choisi. C’est pour ça que j’ai pris le temps de contrôler que c’est bien possible.

Du coup j’ai pris une de mes cellules de sol, et j’ai essayé de trouver sa position à l’image. Et même plus précisement, j’ai besoin d’avoir la position de son centre visuel à l’image.

Centre de ma cellule
J’ai créé un petit vertex pour définir le centre de ma cellule
VertexGroup
Je lui assigne un vertex group pour pouvoir le retrouver. Je ne suis pas encore sûr que ce soit la méthode la plus optimisée.
Ma cellule à côté de la caméra
Et je veux obtenir la position de cette cellule à gauche dans mon image. Mon image étant le carré rouge de 500px par 500px, je suis sensé obtenir une valeur négative en X d’environ 400 et un Y d’environ 250

Je me suis inspiré d’un morceau de Python trouvé sur le net, et je l’ai adapté à mes besoins. Ça donne ça :

import bpy
import bpy_extras


scene = bpy.context.scene
cam = bpy.data.objects['Camera']
obj =  bpy.data.objects['Position.1892']

# Je récupère l'index de mon vertexGroup
gi = obj.vertex_groups["visualCenter"].index
# Je fais le tour de tous les vertices de mon objet
for v in obj.data.vertices:
  # Pour chaque vertex, je fais le tour des groupes
  # auxquels il appartient.
  for g in v.groups:
    # Si le vertex appartient à mon group visualCenter
    if g.group == gi: 
      # Alors je mémorise ses coordonnées dans le monde
      # global.
      co_final = obj.matrix_world @ v.co


# J'utilise ces coordonnées pour savoir où il est
# dans ma vue caméra
co_2d = bpy_extras.object_utils.world_to_camera_view(scene, cam, co_final)


# Je converti ça en positions en pixels en fonction de ma 
# résolution.
render_scale = scene.render.resolution_percentage / 100
render_size = (
    int(scene.render.resolution_x * render_scale),
    int(scene.render.resolution_y * render_scale),
)

# Tadaa
print("Position de mon pixel :", (
      round(co_2d.x * render_size[0]),
      round(co_2d.y * render_size[1]),
))
Tadaa
Tadaa ! x = -373px et y = 267px.

Avec cette info essentielle, je vais pouvoir placer un personnage à cet endroit via javascript. Et vu que c’est un script, je vais pouvoir automatiser ça pour l’ensemble de mes cellules et ce quelque soit la taille et l’angle de ma caméra. Ce qui nous laissera une bonne liberté au moment de la composition de chaque écran (parfois on pourra faire une vue plus éloignée si on a besoin de place, ou au contraire une vue rapprochée en intérieur. Parfois on pourra se mettre plus vue du bas pour montrer des hauteurs, ou au contraire se mettre tout à fait vu du haut quand on a besoin de pouvoir facilement se repérer dans l’espace ou naviguer entre des arbres.)

Un truc de moins à vérifier :)


Tags : ,

Catégories :

Mis à jour :