Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2006-08-02 08:40:50 +0400
committerCampbell Barton <ideasman42@gmail.com>2006-08-02 08:40:50 +0400
commit7ec55d7a62efd4b9d6de24b21b6db766d0099d7f (patch)
tree1e2a332c6f2c379c2dd1477675e8457a8dc70cfc /release
parent70853bbcc7f34069abf6f12d1199394cc2e67cd6 (diff)
Made this script test 4 different collapse locations and use the one that results in the least error.
locations are: smart, middle, v1, and v2 where smart is an attempt to generate a loc that will collapse without loosing volume. This can now collapse a subdivided cube properly.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/bpymodules/BPyMesh.py4
-rw-r--r--release/scripts/bpymodules/BPyMesh_redux.py234
-rw-r--r--release/scripts/mesh_poly_reduce.py1
3 files changed, 133 insertions, 106 deletions
diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py
index fc4f517879f..883ec92ce77 100644
--- a/release/scripts/bpymodules/BPyMesh.py
+++ b/release/scripts/bpymodules/BPyMesh.py
@@ -19,7 +19,9 @@
import Blender
-from BPyMesh_redux import redux # seperated because of its size.
+import BPyMesh_redux # seperated because of its size.
+reload(BPyMesh_redux)
+redux= BPyMesh_redux.redux
# python 2.3 has no reversed() iterator. this will only work on lists and tuples
try:
diff --git a/release/scripts/bpymodules/BPyMesh_redux.py b/release/scripts/bpymodules/BPyMesh_redux.py
index 0f3177ae651..e68c2c617ae 100644
--- a/release/scripts/bpymodules/BPyMesh_redux.py
+++ b/release/scripts/bpymodules/BPyMesh_redux.py
@@ -165,6 +165,68 @@ def redux(ob, REDUX=0.5, BOUNDRY_WEIGHT=2.0, REMOVE_DOUBLES=False, FACE_AREA_WEI
# Basic weighting.
#self.collapse_weight= self.length * (1+ ((ed.v1.no-ed.v2.no).length**2))
self.collapse_weight= 1.0
+
+ def collapse_locations(self, w1, w2):
+ '''
+ Generate a smart location for this edge to collapse to
+ w1 and w2 are vertex location bias
+ '''
+
+ v1co= self.v1.co
+ v2co= self.v2.co
+ v1no= self.v1.no
+ v2no= self.v2.no
+
+ # Basic operation, works fine but not as good as predicting the best place.
+ #between= ((v1co*w1) + (v2co*w2))
+ #self.collapse_loc= between
+
+ # normalize the weights of each vert - se we can use them as scalers.
+ wscale= w1+w2
+ if not wscale: # no scale?
+ w1=w2= 0.5
+ else:
+ w1/=wscale
+ w2/=wscale
+
+ length= self.length
+ between= (v1co+v2co) * 0.5
+
+ # Collapse
+ # new_location = between # Replace tricky code below. this code predicts the best collapse location.
+
+ # Make lines at right angles to the normals- these 2 lines will intersect and be
+ # the point of collapsing.
+
+ # Enlarge so we know they intersect: self.length*2
+ cv1= CrossVecs(v1no, CrossVecs(v1no, v1co-v2co))
+ cv2= CrossVecs(v2no, CrossVecs(v2no, v2co-v1co))
+
+ # Scale to be less then the edge lengths.
+ cv1.normalize()
+ cv2.normalize()
+ cv1 = cv1 * (length* 0.4)
+ cv2 = cv2 * (length* 0.4)
+
+ smart_offset_loc= between + (cv1 + cv2)
+
+ # Now we need to blend between smart_offset_loc and w1/w2
+ # you see were blending between a vert and the edges midpoint, so we cant use a normal weighted blend.
+ if w1 > 0.5: # between v1 and smart_offset_loc
+ #self.collapse_loc= v1co*(w2+0.5) + smart_offset_loc*(w1-0.5)
+ w2*=2
+ w1= 1-w2
+ new_loc_smart= v1co*w1 + smart_offset_loc*w2
+ else: # w between v2 and smart_offset_loc
+ w1*=2
+ w2= 1-w1
+ new_loc_smart= v2co*w2 + smart_offset_loc*w1
+
+ if new_loc_smart.x != new_loc_smart.x: # NAN LOCATION, revert to between
+ new_loc_smart= None
+
+ return new_loc_smart, between, v1co*0.99999 + v2co*0.00001, v1co*0.00001 + v2co*0.99999
+
class collapseFace(object):
__slots__ = 'verts', 'normal', 'area', 'index', 'orig_uv', 'orig_col', 'uv', 'col' # , 'collapse_edge_count'
@@ -329,144 +391,106 @@ def redux(ob, REDUX=0.5, BOUNDRY_WEIGHT=2.0, REMOVE_DOUBLES=False, FACE_AREA_WEI
vert_collapsed= [1] * len(verts)
- def ed_set_collapse_loc(ced):
- v1co= ced.v1.co
- v2co= ced.v2.co
- v1no= ced.v1.no
- v2no= ced.v2.no
-
- # Basic operation, works fine but not as good as predicting the best place.
- #between= ((v1co*w1) + (v2co*w2))
- #ced.collapse_loc= between
-
- # Use the vertex weights to bias the new location.
- w1= vert_weights[ced.key[0]]
- w2= vert_weights[ced.key[1]]
-
- # normalize the weights of each vert - se we can use them as scalers.
- wscale= w1+w2
- if not wscale: # no scale?
- w1=w2= 0.5
- else:
- w1/=wscale
- w2/=wscale
-
- length= ced.length
- between= (v1co+v2co) * 0.5
-
- # Collapse
- # new_location = between # Replace tricky code below. this code predicts the best collapse location.
-
- # Make lines at right angles to the normals- these 2 lines will intersect and be
- # the point of collapsing.
-
- # Enlarge so we know they intersect: ced.length*2
- cv1= CrossVecs(v1no, CrossVecs(v1no, v1co-v2co))
- cv2= CrossVecs(v2no, CrossVecs(v2no, v2co-v1co))
-
- # Scale to be less then the edge lengths.
- cv1.normalize()
- cv2.normalize()
- cv1 = cv1 * (length* 0.4)
- cv2 = cv2 * (length* 0.4)
-
- smart_offset_loc= between + (cv1 + cv2)
-
-
- if (smart_offset_loc-between).length > length/2:
- # New collapse loc is way out, just use midpoint.
- ced.collapse_loc= between
- else:
- # Now we need to blend between smart_offset_loc and w1/w2
- # you see were blending between a vert and the edges midpoint, so we cant use a normal weighted blend.
- if w1 > 0.5: # between v1 and smart_offset_loc
- #ced.collapse_loc= v1co*(w2+0.5) + smart_offset_loc*(w1-0.5)
- w2*=2
- w1= 1-w2
-
-
- ced.collapse_loc= v1co*w1 + smart_offset_loc*w2
- else: # w between v2 and smart_offset_loc
- w1*=2
- w2= 1-w1
- ced.collapse_loc= v2co*w2 + smart_offset_loc*w1
-
- if ced.collapse_loc.x != ced.collapse_loc.x: # NAN LOCATION, revert to between
- ced.collapse_loc= between
# Best method, no quick hacks here, Correction. Should be the best but needs tweaks.
def ed_set_collapse_error(ced):
- i1, i2= ced.key
+ # Use the vertex weights to bias the new location.
+ new_locs= ced.collapse_locations(vert_weights[ced.key[0]], vert_weights[ced.key[1]])
+
+ # Find the connecting faces of the 2 verts.
+ i1, i2= ced.key
test_faces= set()
for i in (i1,i2): # faster then LC's
for f in vert_face_users[i]:
test_faces.add(f[1].index)
-
for f in ced.faces:
test_faces.remove(f.index)
- # test_faces= tuple(test_faces) # keep order
v1_orig= Vector(ced.v1.co)
v2_orig= Vector(ced.v2.co)
- ced.v1.co= ced.v2.co= ced.collapse_loc
-
- new_nos= [faces[i].no for i in test_faces]
-
- ced.v1.co= v1_orig
- ced.v2.co= v2_orig
+ def test_loc(new_loc):
+ '''
+ Takes a location and tests the error without changing anything
+ '''
+ new_weight= ced.collapse_weight
+ ced.v1.co= ced.v2.co= new_loc
+
+ new_nos= [faces[i].no for i in test_faces]
+
+ # So we can compare the befire and after normals
+ ced.v1.co= v1_orig
+ ced.v2.co= v2_orig
+
+ # now see how bad the normals are effected
+ angle_diff= 1.0
+
+ for ii, i in enumerate(test_faces): # local face index, global face index
+ cfa= collapse_faces[i] # this collapse face
+ try:
+ # can use perim, but area looks better.
+ if FACE_AREA_WEIGHT:
+ # Psudo code for wrighting
+ # angle_diff= The before and after angle difference between the collapsed and un-collapsed face.
+ # ... devide by 180 so the value will be between 0 and 1.0
+ # ... add 1 so we can use it as a multiplyer and not make the area have no eefect (below)
+ # area_weight= The faces original area * the area weight
+ # ... add 1.0 so a small area face dosent make the angle_diff have no effect.
+ #
+ # Now multiply - (angle_diff * area_weight)
+ # ... The weight will be a minimum of 1.0 - we need to subtract this so more faces done give the collapse an uneven weighting.
+
+ angle_diff+= ((1+(Ang(cfa.normal, new_nos[ii])/180)) * (1+(cfa.area * FACE_AREA_WEIGHT))) -1 # 4 is how much to influence area
+ else:
+ angle_diff+= (Ang(cfa.normal), new_nos[ii])/180
+
+ except:
+ pass
+
+
+ # This is very arbirary, feel free to modify
+ try: no_ang= (Ang(ced.v1.no, ced.v2.no)/180) + 1
+ except: no_ang= 2.0
+
+ # do *= because we face the boundry weight to initialize the weight. 1.0 default.
+ new_weight *= ((no_ang * ced.length) * (1-(1/angle_diff)))# / max(len(test_faces), 1)
+ return new_weight
+ # End testloc
- # now see how bad the normals are effected
- angle_diff= 1.0
- for ii, i in enumerate(test_faces): # local face index, global face index
- cfa= collapse_faces[i] # this collapse face
- try:
- # can use perim, but area looks better.
- if FACE_AREA_WEIGHT:
- # Psudo code for wrighting
- # angle_diff= The before and after angle difference between the collapsed and un-collapsed face.
- # ... devide by 180 so the value will be between 0 and 1.0
- # ... add 1 so we can use it as a multiplyer and not make the area have no eefect (below)
- # area_weight= The faces original area * the area weight
- # ... add 1.0 so a small area face dosent make the angle_diff have no effect.
- #
- # Now multiply - (angle_diff * area_weight)
- # ... The weight will be a minimum of 1.0 - we need to subtract this so more faces done give the collapse an uneven weighting.
-
- angle_diff+= ((1+(Ang(cfa.normal, new_nos[ii])/180)) * (1+(cfa.area * FACE_AREA_WEIGHT))) -1 # 4 is how much to influence area
- else:
- angle_diff+= (Ang(cfa.normal), new_nos[ii])/180
-
- except:
- pass
+ # Test the collapse locatons
+ collapse_loc_best= None
+ collapse_weight_best= 1000000000
+ ii= 0
+ for collapse_loc in new_locs:
+ if collapse_loc: # will only ever fail if smart loc is NAN
+ test_weight= test_loc(collapse_loc)
+ if test_weight < collapse_weight_best:
+ iii= ii
+ collapse_weight_best = test_weight
+ collapse_loc_best= collapse_loc
+ ii+=1
- # This is very arbirary, feel free to modify
- try: no_ang= (Ang(ced.v1.no, ced.v2.no)/180) + 1
- except: no_ang= 2.0
-
- # do *= because we face the boundry weight to initialize the weight. 1.0 default.
- ced.collapse_weight*= ((no_ang * ced.length) * (1-(1/angle_diff)))# / max(len(test_faces), 1)
+ ced.collapse_loc= collapse_loc_best
+ ced.collapse_weight= collapse_weight_best
# are we using a weight map
if VGROUP_INF_REDUX:
v= vert_weights_map[i1]+vert_weights_map[i2]
ced.collapse_weight*= v
-
+ # End collapse Error
# We can calculate the weights on __init__ but this is higher qualuity.
for ced in collapse_edges:
if ced.faces: # dont collapse faceless edges.
- ed_set_collapse_loc(ced)
ed_set_collapse_error(ced)
# Wont use the function again.
del ed_set_collapse_error
- del ed_set_collapse_loc
# END BOUNDRY. Can remove
# sort by collapse weight
diff --git a/release/scripts/mesh_poly_reduce.py b/release/scripts/mesh_poly_reduce.py
index af965f4b6a5..de84ec6b300 100644
--- a/release/scripts/mesh_poly_reduce.py
+++ b/release/scripts/mesh_poly_reduce.py
@@ -16,6 +16,7 @@ This script simplifies the mesh by removing faces, keeping the overall shape of
from Blender import Draw, Window, Scene, Mesh, Mathutils, sys, Object
import BPyMesh
+reload(BPyMesh)
# ***** BEGIN GPL LICENSE BLOCK *****
#