I know how to get these information in the whole scene with Python, but now I want to get them only in camera view. Or can blender export any documents including these information ?
-
what about objects that are only partially in view, are you going to only count the visible part? – David Apr 28 '17 at 12:35
-
The code in this link calculates the UV coordinates from the camera 3D projection. You can use the same principle to check vertices that are in the camera field (in field if all co between 0 and 1). https://blender.stackexchange.com/questions/76774/projecting-multiple-images-onto-an-object-with-uv-project-modifiers/77108#77108 – lemon Apr 28 '17 at 15:34
-
@David Only visible parts, since I want to do something with rendering. – rita33cool1 Apr 29 '17 at 14:19
-
@lemon Thank you very much. Now I have to read it for a while to understand it, but it looks like what I want. – rita33cool1 Apr 29 '17 at 14:29
-
@lemon What does "in field if all co between 0 and 1" mean? After reading these principles, I am confuse what I can do with these principles? First, do I need to project something onto something? Second, in my project, the camera has been determined, I can't change it. So do I still can use these principles? – rita33cool1 May 01 '17 at 01:58
1 Answers
Following your question in the comments below your question, I give here a partial answer and some guidelines (but the complete code is too long to do for me).
So just some code snippets:
CameraSetting class: allow to calculate the projection of a vertex in the camera/view given a mesh object. This code does the same as bpy_extras.object_utils.world_to_camera_view(scene, cam, co) but it calculates many things once instead of doing it for each 'co'. See here.
CountForObject function: provide a simple calculation of the vertices included in the view of a camera.
Note also that you can optimize the calculation by checking the bounding box of the objects before calculating all their vertices projections.
Hope it can help (the code contains additional comments):
import bpy
import time
from mathutils import Vector
from operator import itemgetter
#Used to store information related to a camera setting for a given object
class CameraSetting:
def __init__( self, scene, camera, obj ):
self.camera = camera
#Z axis of the camera translate in world (Z axis is opposite to view)
self.zInWorld = Vector( (0, 0, 1) )
self.zInWorld.rotate( self.camera.matrix_world.to_euler() )
#Camera parameters
#Matrix to convert from object coordinate to camera coordinates
self.toCameraMatrix = camera.matrix_world.inverted() * obj.matrix_world
#The frame is composed of the coordinates in the camera view
frame = [v / v.z for v in camera.data.view_frame(scene=scene)]
#Get the X, Y corners
self.minX = min( v.x for v in frame )
self.maxX = max( v.x for v in frame )
self.minY = min( v.y for v in frame )
self.maxY = max( v.y for v in frame )
#Precalculations to avoid to repeat them when applied to the model
self.deltaX = self.maxX - self.minX
self.deltaY = self.maxY - self.minY
self.offsetX = self.minX / self.deltaX
self.offsetY = self.minY / self.deltaY
#Calculate projected coordinateds from the object coordinates
def CalcProjected( self, objCo ):
#Object coordinate in camera view
camCo = self.toCameraMatrix * objCo
#Z is "inverted" as camera view is pointing to -Z of the camera
z = -camCo.z
try:
#Translates x and y to projected coordinates
x = (camCo.x / (self.deltaX * z)) - self.offsetX
y = (camCo.y / (self.deltaY * z)) - self.offsetY
return x, y, z
except:
#In case Z is zero
return 0.5, 0.5, 0
def CountForObject( scene, obj, cam ):
matrix_world = obj.matrix_world
rotation_world = matrix_world.to_euler()
vertices = obj.data.vertices
camSetting = CameraSetting( scene, cam, obj )
vertexCount = 0
#Go through all polygons
for v in obj.data.vertices:
x, y, z = camSetting.CalcProjected( v.co )
if 0 <= x <= 1 and 0 <= y <= 1 and z >= 0:
vertexCount += 1
#z can be tested to see if its correspond to the camera clipping (cam.data.clip_start/cam.data.clip_end)
#This calculation allows to check x and y
#x and y are between 0 and 1 if in the camera field (because CalcProjected do so)
#From that you can consider that all edges and faces which have a good vertex are in field too
#But for the remaining edges you'll need to check if the corresponding vertices projection intersects the (0,0) to (1,1) square
#Then consider the polygons that correspond to these edges to count them two
print( vertexCount )
scene = bpy.context.scene
obj = bpy.data.objects['Cube']
cam = bpy.data.objects['Camera']
CountForObject( scene, obj, cam )
- 60,295
- 3
- 66
- 136
-
Thanks for your help, you do gave me a big favor!!! Now I can get what I want. – rita33cool1 May 05 '17 at 08:51