-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblender_mappy.py
164 lines (146 loc) · 6.15 KB
/
blender_mappy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
bl_info = {
"name": "Match Area Light",
"author": "Anthony Aragues",
"version": (1, 2),
"blender": (2, 90, 0),
"location": "n > Lights",
"description": "Rapidly create area lights to match size and orientation of selected faces",
"warning": "",
"doc_url": "",
"category": "Lighting",
}
# This example assumes we have a mesh object in edit-mode
import bpy, bmesh
from mathutils import Vector, Matrix
'''
import bpy
import bmesh
context = bpy.context
ob = context.edit_object
mw = ob.matrix_world
me = ob.data
bm = bmesh.from_edit_mesh(me)
faces = [f for f in bm.faces if f.select]
while faces:
f = faces.pop()
light = bpy.data.lights.new(
f"Face{f.index}",
type='AREA',
)
light.size = 1
light_ob = bpy.data.objects.new(
f"Face{f.index}",
light,
)
M = mw.normalized() @ f.normal.to_track_quat('-Z', 'Y').to_matrix().to_4x4()
M.translation = mw @ f.calc_center_median()
light_ob.matrix_world = M
context.collection.objects.link(light_ob)
'''
def fnGetScale(objFace):
intMinX = None
intMinY = None
intMinZ = None
intMaxX = None
intMaxY = None
intMaxZ = None
for objVert in objFace.verts:
#coordinates per point per face of selected object
arrCo=objVert.co.to_tuple()
if intMinX == None or arrCo[0] < intMinX:
intMinX=arrCo[0]
if intMaxX == None or arrCo[0] > intMaxX:
intMaxX=arrCo[0]
if intMinY == None or arrCo[1] < intMinY:
intMinY=arrCo[1]
if intMaxY == None or arrCo[1] > intMaxY:
intMaxY=arrCo[1]
if intMinZ == None or arrCo[2] < intMinZ:
intMinZ=arrCo[2]
if intMaxZ == None or arrCo[2] > intMaxZ:
intMaxZ=arrCo[2]
return {"x":intMaxX-intMinX,"y":intMaxY-intMinY,"z":intMaxZ-intMinZ}
class LightsOp(bpy.types.Operator):
bl_idname = 'lights.go'
bl_label = 'Map Area Light to All Selected'
#this is the operator function that will be called on button press
def execute(self, context):
# Get the active mesh
obj = context.edit_object
bpy.ops.object.editmode_toggle()
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
bpy.ops.object.editmode_toggle()
objMesh = bmesh.from_edit_mesh(obj.data)
#create the lights
arrLights=[]
for objFace in objMesh.faces:
if objFace.select == True:
objLight={'location':{}, 'direction':{}, 'matrix':{}, 'scale':{'x':0,'y':0,'z':0}}
objCenter= objFace.calc_center_median()
objLight['location']=objCenter.to_tuple()
objLight['direction']=objFace.normal
intMinX = None
intMinY = None
intMinZ = None
intMaxX = None
intMaxY = None
intMaxZ = None
for objVert in objFace.verts:
#coordinates per point per face of selected object
arrCo=objVert.co.to_tuple()
if intMinX == None or arrCo[0] < intMinX:
intMinX=arrCo[0]
if intMaxX == None or arrCo[0] > intMaxX:
intMaxX=arrCo[0]
if intMinY == None or arrCo[1] < intMinY:
intMinY=arrCo[1]
if intMaxY == None or arrCo[1] > intMaxY:
intMaxY=arrCo[1]
if intMinZ == None or arrCo[2] < intMinZ:
intMinZ=arrCo[2]
if intMaxZ == None or arrCo[2] > intMaxZ:
intMaxZ=arrCo[2]
objLight['scale']['x'] = intMaxX-intMinX
objLight['scale']['y'] = intMaxY-intMinY
objLight['scale']['z'] = intMaxZ-intMinZ
objMatrix=obj.matrix_world.normalized() @ objFace.normal.to_track_quat('-Z', 'Y').to_matrix().to_4x4()
objMatrix.translation = obj.matrix_world @ objFace.calc_center_median()
objLight['matrix']=objMatrix
print(objLight)
arrLights.append(objLight)
bpy.ops.object.editmode_toggle()
for intLight,objLight in enumerate(arrLights):
objNewLight=bpy.ops.object.light_add(type='AREA', radius=1, align='WORLD', location=objLight['location'])
# set the rotation the light in the direction of the normal
context.object.matrix_world=objLight['matrix']
#bpy.context.object.rotation_mode = 'QUATERNION'
#bpy.context.object.rotation_quaternion = objLight['direction'].to_track_quat('Z','Y')
#bpy.context.object.scale( objLight['scale']['x'],objLight['scale']['y'],objLight['scale']['z'] )
bpy.ops.transform.resize(value=(objLight['scale']['x']/1, objLight['scale']['y']/1, objLight['scale']['z']/1), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)),
orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
return {"FINISHED"}
class LightsPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Light"
bl_category = "Lights"
bl_idname = "Light_Panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
def draw(self, context):
layout = self.layout
#start with first camera found
row = layout.row()
row.label(text="Create area lights from faces")
row = layout.row()
row.label(text="1. Selected faces in edit mode")
row = layout.row()
row.label(text="2. Run the tool")
layout.operator("lights.go",text = 'Create area lights')
def register():
bpy.utils.register_class(LightsOp)
bpy.utils.register_class(LightsPanel)
def unregister():
bpy.utils.unregister_class(LightsOp)
bpy.utils.unregister_class(LightsPanel)
if __name__ == "__main__":
register()