Created
February 9, 2014 15:33
-
-
Save thebusytypist/8900746 to your computer and use it in GitHub Desktop.
SelectVisibleVertices Blender operator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Select Visible Vertices", | |
"category": "Object", | |
} | |
import bpy | |
import mathutils | |
import bmesh | |
def Frustum(l, r, b, t, n, f): | |
return mathutils.Matrix(( | |
(2 * n / (r - l), 0, (r + l) / (r - l), 0), | |
(0, 2 * n / (t - b), (t + b) / (t - b), 0), | |
(0, 0, -(f + n) / (f - n), -2 * f * n / (f - n)), | |
(0, 0, -1, 0) | |
)) | |
def IsVisible(ndc): | |
return ndc.x <= 1 and ndc.x >= -1 and ndc.y <= 1 and ndc.y >= -1 and ndc.z <= 1 and ndc.z >= -1 | |
def Select(mvp, mesh): | |
bm = bmesh.new() | |
bm.from_mesh(mesh) | |
for v in bm.verts: | |
c = v.co | |
# Convert to homogeneous coordinate | |
h = mathutils.Vector((c.x, c.y, c.z, 1)) | |
t = mvp * h | |
# w-division | |
ndc = t.xyz / t.w | |
if IsVisible(ndc): | |
v.select_set(True) | |
return bm | |
class SelectVisibleVertices(bpy.types.Operator): | |
"""Select visible vertices""" # blender will use this as a tooltip for menu items and buttons. | |
bl_idname = "object.select_visible_vertices" # unique identifier for buttons and menu items to reference. | |
bl_label = "Select visible vertices" # display name in the interface. | |
bl_options = {"REGISTER", "UNDO"} # enable undo for the operator. | |
def execute(self, context): # execute() is called by blender when running the operator. | |
scene = context.scene | |
# Get the active object | |
object = scene.objects.active | |
mesh = object.data | |
# Get active camera | |
camera_object = scene.camera | |
camera = camera_object.data | |
# Switch to edit mode | |
bpy.ops.object.mode_set(mode="EDIT") | |
# Set select mode to "vertex" | |
context.tool_settings.mesh_select_mode = [True, False, False] | |
# Deselect all vertices | |
bpy.ops.mesh.select_all(action = "DESELECT") | |
# Toggle mode to update the selection state | |
bpy.ops.object.mode_set(mode="OBJECT") | |
bpy.ops.object.mode_set(mode="EDIT") | |
# Projection transformation | |
view_frame = camera.view_frame(scene) | |
near = camera.clip_start | |
far = camera.clip_end | |
left, top = view_frame[3].xy / 2 | |
right, bottom = view_frame[1].xy / 2 | |
proj = Frustum(left, right, bottom, top, near, far) | |
# View transformation | |
view = camera_object.matrix_world.inverted() | |
# Object world transformation | |
model = object.matrix_world | |
# Model-View-Projection transformation | |
m = proj * view * model | |
bm = Select(m, mesh) | |
# Switch to object mode | |
bpy.ops.object.mode_set(mode="OBJECT") | |
# Update mesh | |
bm.to_mesh(mesh) | |
mesh.update() | |
# Back to edit mode to see the result | |
bpy.ops.object.mode_set(mode="EDIT") | |
return {'FINISHED'} # this lets blender know the operator finished successfully. | |
def register(): | |
bpy.utils.register_class(SelectVisibleVertices) | |
def unregister(): | |
bpy.utils.unregister_class(SelectVisibleVertices) | |
# This allows you to run the script directly from blenders text editor | |
# to test the addon without having to install it. | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment