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 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
from Blender import *
try:
import psyco
psyco.full()
except:
print 'no psyco for you!'
DotVecs= Mathutils.DotVecs
#========================================================
# SPACIAL TREE - Seperate Class - use if you want to
# USed for getting vert is a proximity
LEAF_SIZE = 128
class octreeNode:
def __init__(self, verts, parent):
# Assunme we are a leaf node, until split is run.
self.verts = verts
self.children = []
if parent == None: # ROOT NODE, else set bounds when making children,
# BOUNDS
v= verts[0]
maxx,maxy,maxz= v.co
minx,miny,minz= maxx,maxy,maxz
for v in verts:
x,y,z= v.co
if x>maxx: maxx= x
if y>maxy: maxy= y
if z>maxz: maxz= z
if x<minx: minx= x
if y<miny: miny= y
if z<minz: minz= z
self.minx= minx
self.miny= miny
self.minz= minz
self.maxx= maxx
self.maxy= maxy
self.maxz= maxz
# We have no parent to split us so split ourselves.
#self.setCornerPoints()
self.splitNode()
def splitNode(self):
if len(self.verts) > LEAF_SIZE:
self.makeChildren() # 8 new children,
self.verts = None
# Alredy assumed a leaf not so dont do anything here.
def makeChildren(self):
verts= self.verts
# Devide into 8 children.
axisDividedVerts = [[],[],[],[],[],[],[],[]] # Verts Only
divx = (self.maxx + self.minx) / 2
divy = (self.maxy + self.miny) / 2
divz = (self.maxz + self.minz) / 2
# Sort into 8
for v in verts:
x,y,z = v.co
if x > divx:
if y > divy:
if z > divz:
axisDividedVerts[0].append(v)
else:
axisDividedVerts[1].append(v)
else:
if z > divz:
axisDividedVerts[2].append(v)
else:
axisDividedVerts[3].append(v)
else:
if y > divy:
if z > divz:
axisDividedVerts[4].append(v)
else:
axisDividedVerts[5].append(v)
else:
if z > divz:
axisDividedVerts[6].append(v)
else:
axisDividedVerts[7].append(v)
# populate self.children
for i in xrange(8):
octNode = octreeNode(axisDividedVerts[i], self)
# Set bounds manually
if i == 0:
octNode.minx = divx
octNode.maxx = self.maxx
octNode.miny = divy
octNode.maxy = self.maxy
octNode.minz = divz
octNode.maxz = self.maxz
elif i == 1:
octNode.minx = divx
octNode.maxx = self.maxx
octNode.miny = divy
octNode.maxy = self.maxy
octNode.minz = self.minz #
octNode.maxz = divz #
elif i == 2:
octNode.minx = divx
octNode.maxx = self.maxx
octNode.miny = self.miny #
octNode.maxy = divy #
octNode.minz = divz
octNode.maxz = self.maxz
elif i == 3:
octNode.minx = divx
octNode.maxx = self.maxx
octNode.miny = self.miny #
octNode.maxy = divy #
octNode.minz = self.minz #
octNode.maxz = divz #
elif i == 4:
octNode.minx = self.minx #
octNode.maxx = divx #
octNode.miny = divy
octNode.maxy = self.maxy
octNode.minz = divz
octNode.maxz = self.maxz
elif i == 5:
octNode.minx = self.minx #
octNode.maxx = divx #
octNode.miny = divy
octNode.maxy = self.maxy
octNode.minz = self.minz #
octNode.maxz = divz #
elif i == 6:
octNode.minx = self.minx #
octNode.maxx = divx #
octNode.miny = self.miny #
octNode.maxy = divy #
octNode.minz = divz
octNode.maxz = self.maxz
elif i == 7:
octNode.minx = self.minx #
octNode.maxx = divx #
octNode.miny = self.miny #
octNode.maxy = divy #
octNode.minz = self.minz #
octNode.maxz = divz #
#octNode.setCornerPoints()
octNode.splitNode() # Splits the node if it can.
self.children.append(octNode)
# GETS VERTS IN A Distance RANGE-
def getVertsInRange(self, loc, normal, range_val, vertList):
#loc= Mathutils.Vector(loc) # MUST BE VECTORS
#normal= Mathutils.Vector(normal)
'''
loc: Vector of the location to search from
normal: None or Vector - if a vector- will only get verts on this side of the vector
range_val: maximum distance. A negative value will fill the list with teh closest vert only.
vertList: starts as an empty list
list that this function fills with verts that match
'''
xloc,yloc,zloc= loc
if range_val<0:
range_val= -range_val
FIND_CLOSEST= True
vertList.append(None) # just update the 1 vertex
else:
FIND_CLOSEST= False
if self.children:
# Check if the bounds are in range_val,
for childNode in self.children:
# First test if we are surrounding the point.
if\
childNode.minx - range_val < xloc and\
childNode.maxx + range_val > xloc and\
childNode.miny - range_val < yloc and\
childNode.maxy + range_val > yloc and\
childNode.minz - range_val < zloc and\
childNode.maxz + range_val > zloc:
# Recurse down or get virts.
childNode.getVertsInRange(loc, normal, range_val, vertList)
#continue # Next please
else: # we are a leaf node. Test vert locations.
if not normal:
# Length only check
for v in self.verts:
length = (loc - v.co).length
if length < range_val:
if FIND_CLOSEST:
# Just update the 1 vert
vertList[0]= (v, length)
range_val= length # Shink the length so we only get verts from their.
else:
vertList.append((v, length))
else:
# Lengh and am I infront of the vert.
for v in self.verts:
length = (loc - v.co).length
if length < range_val:
# Check if the points in front
dot= DotVecs(normal, loc) - DotVecs(normal, v.co)
if dot<0:
vertList.append((v, length))
# END TREE
# EXAMPLE RADIO IN PYTHON USING THE ABOVE FUNCTION
"""
import BPyMesh
# Radio bake
def bake():
_AngleBetweenVecs_= Mathutils.AngleBetweenVecs
def AngleBetweenVecs(a1,a2):
try:
return _AngleBetweenVecs_(a1,a2)
except:
return 180
scn = Scene.GetCurrent()
ob = scn.getActiveObject()
me = ob.getData(mesh=1)
dist= Draw.PupFloatInput('MaxDist:', 2.0, 0.1, 20.0, 0.1, 3)
if dist==None:
return
# Make nice normals
BPyMesh.meshCalcNormals(me)
len_verts= len(me.verts)
#me.sel= False
meshOctTree = octreeNode(me.verts, None)
# Store face areas
vertex_areas= [0.0] * len_verts
# Get vertex areas - all areas of face users
for f in me.faces:
a= f.area
for v in f.v:
vertex_areas[v.index] += a
bias= 0.001
t= sys.time()
# Tone for the verts
vert_tones= [0.0] * len_verts
maxtone= 0.0
mintone= 100000000
for i, v in enumerate(me.verts):
if not i%10:
print 'verts to go', len_verts-i
v_co= v.co
v_no= v.no
verts_in_range= []
meshOctTree.getVertsInRange(v_co, v_no, dist, verts_in_range)
tone= 0.0
# These are verts in our range
for test_v, length in verts_in_range:
if bias<length:
try:
# Make sure this isnt a back facing vert
normal_diff= AngleBetweenVecs(test_v.no, v_no)
except:
continue
if normal_diff > 90: # were facing this vert
#if 1:
# Current value us between zz90 and 180
# make between 0 and 90
# so 0 is right angles and 90 is direct opposite vertex normal
normal_diff= (normal_diff-90)
# Vertex area needs to be taken into account so we dont have small faces over influencing.
vertex_area= vertex_areas[test_v.index]
# Get the angle the vertex is in location from the location and normal of the vert.
above_diff= AngleBetweenVecs(test_v.co-v.co, v_no)
## Result will be between 0 :above and 90: horizon.. invert this so horizon has littel effect
above_diff= 90-above_diff
# dist-length or 1.0/length both work well
tone= (dist-length) * vertex_area * above_diff * normal_diff
vert_tones[i] += tone
if maxtone<vert_tones[i]:
maxtone= vert_tones[i]
if mintone>vert_tones[i]:
mintone= vert_tones[i]
if not maxtone:
Draw.PupMenu('No verts in range, use a larger range')
return
# Apply tones
for f in me.faces:
f_col= f.col
for i, v in enumerate(f.v):
c= f_col[i]
v_index= v.index
tone= int(((maxtone - vert_tones[v.index]) / maxtone) * 255 )
#print tone
c.r= c.g= c.b= tone
print 'time', sys.time()-t
if __name__=="__main__":
bake()
"""
|