Skip to content

Instantly share code, notes, and snippets.

@zeffii
Forked from anonymous/boomstick.py
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeffii/686b6a5482bf8a6f49df to your computer and use it in GitHub Desktop.
Save zeffii/686b6a5482bf8a6f49df to your computer and use it in GitHub Desktop.
import bpy
import bgl
import blf
import bmesh
from mathutils import Vector, Matrix
from collections import defaultdict
import sys
from sverchok.utils import (
sv_bmesh_utils,
csg_core,
csg_geom
)
from sverchok.utils.csg_core import CSG
from sverchok.utils.sv_bmesh_utils import (
pydata_from_bmesh,
bmesh_from_pydata
)
Scene = bpy.types.Scene
def new_obj(bm, named_object, named_mesh):
me = bpy.data.meshes.new(named_mesh)
bm.to_mesh(me)
bm.free()
scene = bpy.context.scene
obj = bpy.data.objects.new(named_object, me)
scene.objects.link(obj)
return obj
def generate_draw_geometry(caller, context):
bm = bmesh.new()
obj = bpy.context.active_object
me = obj.data
bm.from_mesh(me)
original_face = bm.faces.active
verts = [v.co.copy() for v in original_face.verts]
face_normal = original_face.normal.copy()
bm.free()
del bm
return verts, face_normal, obj.matrix_world.copy()
def generate_boolean_geom(verts, normal, scalar):
bm = bmesh.new()
final_verts = []
num_verts = len(verts)
faces = []
face1 = []
face2 = []
ftwix = []
for idx, v in enumerate(verts):
final_verts.append(v)
face1.append(idx)
for idx, v in enumerate(verts, num_verts):
final_verts.append(v + (normal * scalar))
face2.append(idx)
for idx, _ in enumerate(verts):
idx_1 = idx
idx_2 = (idx + 1) % num_verts
idx_3 = ((idx + 1) % num_verts) + num_verts
idx_4 = idx + num_verts
ftwix.append([idx_1, idx_2, idx_3, idx_4])
faces.append(face1)
faces.append(face2)
faces.extend(ftwix)
return final_verts, faces
def generate_result(VA, PA, VB, PB):
a = CSG.Obj_from_pydata(VA, PA)
b = CSG.Obj_from_pydata(VB, PB)
recursionlimit = sys.getrecursionlimit()
sys.setrecursionlimit(10000)
try:
# polygons = a.union(b).toPolygons()
polygons = a.intersect(b).toPolygons()
# polygons = a.subtract(b).toPolygons()
except RuntimeError as e:
raise RuntimeError(e)
sys.setrecursionlimit(recursionlimit)
faces = []
vertices = []
for polygon in polygons:
indices = []
for v in polygon.vertices:
pos = [v.pos.x, v.pos.y, v.pos.z]
if not (pos in vertices):
vertices.append(pos)
index = vertices.index(pos)
indices.append(index)
faces.append(indices)
return vertices, faces
def draw_callback_px(self, context, res):
verts, fnorm, fmatrix = res
scn = context.scene
scalar = scn.BGL_OFFSET_SCALAR
# 50% alpha, 2 pixel width line
bgl.glEnable(bgl.GL_BLEND)
bgl.glLineWidth(context.scene.BGL_DEMO_PROP_THICKNESS)
bgl.glColor4f(0.8, 0.3, 0.9, 1.0)
bgl.glBegin(bgl.GL_LINE_LOOP)
for vert in verts:
co = fmatrix * (vert + (fnorm * scalar))
bgl.glVertex3f(*co)
bgl.glEnd()
# restore opengl defaults
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
class ModalDrawOperator(bpy.types.Operator):
bl_idname = "view3d.bgl_demo_modal_operator"
bl_label = "Simple Modal View3D Operator"
def modal(self, context, event):
context.area.tag_redraw()
scn = context.scene
if event.type in {'MIDDLEMOUSE'}:
return {'RUNNING_MODAL'}
if event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
if event.type in {'RET'}:
scalar = scn.BGL_OFFSET_SCALAR
VB, PB = generate_boolean_geom(self.verts, self.normal, scalar) # extract this
if False:
bm = bmesh_from_pydata(VB, [], PB)
new_obj(bm, "ExtractObject", "Extract_mesh")
obj = bpy.context.active_object
me = obj.data
bm = bmesh.new()
bm.from_mesh(me) # from this
VA, _, PA = pydata_from_bmesh(bm)
bm.free()
v, f = generate_result(VA, PA, VB, PB)
bm = bmesh_from_pydata(v, [], f)
bm.to_mesh(me)
bm.free() # free and prevent further access
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
return {'PASS_THROUGH'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
scn = context.scene
scn.BGL_OFFSET_SCALAR = 0.0
scn.BGL_DEMO_PROP_THICKNESS = 5
res = generate_draw_geometry(self, context)
self.verts = res[0]
self.normal = res[1]
self.scalar = res[2]
args = (self, context, res)
draw_handler_add = bpy.types.SpaceView3D.draw_handler_add
self._handle = draw_handler_add(
draw_callback_px, args, 'WINDOW', 'POST_VIEW')
bpy.ops.object.mode_set(mode='OBJECT')
context.active_object.show_wire = True
context.active_object.show_all_edges = True
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
# bl_context = "object"
def draw(self, context):
layout = self.layout
col = layout.column()
col.prop(context.scene, 'BGL_DEMO_PROP_THICKNESS', text='thickness')
col.prop(context.scene, 'BGL_OFFSET_SCALAR', text='amount')
col.operator("view3d.bgl_demo_modal_operator")
def register():
Scene.BGL_DEMO_PROP_THICKNESS = bpy.props.IntProperty(default=1, max=5)
Scene.BGL_OFFSET_SCALAR = bpy.props.FloatProperty(
min=-5.0, max=5.0, default=0.0)
bpy.utils.register_class(HelloWorldPanel)
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(HelloWorldPanel)
bpy.utils.unregister_class(ModalDrawOperator)
del Scene.BGL_OFFSET_SCALAR
del Scene.BGL_DEMO_PROP_THICKNESS
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment