0
$\begingroup$

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 ?

$\endgroup$
  • $\begingroup$ what about objects that are only partially in view, are you going to only count the visible part? $\endgroup$ – David Apr 28 '17 at 12:35
  • $\begingroup$ 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). blender.stackexchange.com/questions/76774/… $\endgroup$ – lemon Apr 28 '17 at 15:34
  • $\begingroup$ @David Only visible parts, since I want to do something with rendering. $\endgroup$ – rita33cool1 Apr 29 '17 at 14:19
  • $\begingroup$ @lemon Thank you very much. Now I have to read it for a while to understand it, but it looks like what I want. $\endgroup$ – rita33cool1 Apr 29 '17 at 14:29
  • $\begingroup$ @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? $\endgroup$ – rita33cool1 May 1 '17 at 1:58
2
$\begingroup$

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 )
$\endgroup$
  • $\begingroup$ Thanks for your help, you do gave me a big favor!!! Now I can get what I want. $\endgroup$ – rita33cool1 May 5 '17 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.