[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2125] trunk/py/scripts/addons/ object_grease_scatter.py: initial commit of grease scatter script, still needs updating.

Campbell Barton ideasman42 at gmail.com
Sun Jul 17 15:03:06 CEST 2011


Revision: 2125
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2125
Author:   campbellbarton
Date:     2011-07-17 13:03:05 +0000 (Sun, 17 Jul 2011)
Log Message:
-----------
initial commit of grease scatter script, still needs updating.

Added Paths:
-----------
    trunk/py/scripts/addons/object_grease_scatter.py

Added: trunk/py/scripts/addons/object_grease_scatter.py
===================================================================
--- trunk/py/scripts/addons/object_grease_scatter.py	                        (rev 0)
+++ trunk/py/scripts/addons/object_grease_scatter.py	2011-07-17 13:03:05 UTC (rev 2125)
@@ -0,0 +1,426 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# Script copyright (C) Campbell Barton
+
+bl_info = {
+    "name": "Export Camera Animation",
+    "author": "Campbell Barton",
+    "version": (0, 1),
+    "blender": (2, 5, 8),
+    "api": 36079,
+    "location": "File > Export > Cameras & Markers (.py)",
+    "description": "Export Cameras & Markers (.py)",
+    "warning": "",
+    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
+        "Scripts/Object/Grease_Scatter",
+    "tracker_url": "https://projects.blender.org/tracker/index.php?"\
+        "func=detail&aid=TODO",
+    "support": 'OFFICIAL',
+    "category": "Object"}
+
+from mathutils import Vector, RotationMatrix, Quaternion
+from math import radians
+from random import uniform, shuffle
+import bpy
+
+def _main(self, DENSITY=1.0, SCALE=0.6, RAND_LOC=0.8, RAND_ALIGN=0.75):
+    from math import radians
+    
+    C = bpy.context
+    o = C.object
+    # print(o.ray_cast(Vector(), Vector(0,0,0.2)))
+    
+    OFS = 0.2
+    SEEK = 2.0 # distance for ray to seek
+    BAD_NORMAL = Vector((0,0,-1))
+    WALL_LIMIT = radians(45.0)
+
+    mats = [
+    RotationMatrix(radians(-45), 3, 'X'),
+    RotationMatrix(radians( 45), 3, 'X'),
+    RotationMatrix(radians(-45), 3, 'Y'),
+    RotationMatrix(radians( 45), 3, 'Y'),
+    RotationMatrix(radians(-45), 3, 'Z'),
+    RotationMatrix(radians( 45), 3, 'Z')]
+
+
+    Z_UP = Vector((0,0,1.0))
+    dirs = [
+    Vector((0,0,OFS)),
+    Vector((0,0,-OFS))]
+    '''
+    Vector(0,OFS,0),
+    Vector(0,-OFS,0),
+    Vector(OFS,0,0),
+    Vector(-OFS,0,0)
+    '''
+    
+    group = bpy.data.groups.get(o.name)
+    
+    if not group:
+        self.report({'WARNING'}, "Group '%s' not found, must match object name" % o.name)
+        return
+
+    def faces_from_hits(hit_list):
+        def from_pydata(self, verts, edges, faces):
+            """
+            Make a mesh from a list of verts/edges/faces
+            Until we have a nicer way to make geometry, use this.
+            """
+            self.add_geometry(len(verts), len(edges), len(faces))
+
+            verts_flat = [f for v in verts for f in v]
+            self.verts.foreach_set("co", verts_flat)
+            del verts_flat
+
+            edges_flat = [i for e in edges for i in e]
+            self.edges.foreach_set("verts", edges_flat)
+            del edges_flat
+
+            def treat_face(f):
+                if len(f) == 3:
+                    return f[0], f[1], f[2], 0
+                elif f[3] == 0:
+                    return f[3], f[0], f[1], f[2]
+                return f
+
+            faces_flat = [v for f in faces for v in treat_face(f)]
+            self.faces.foreach_set("verts_raw", faces_flat)
+            del faces_flat
+        
+        
+
+
+    def debug_edge(v1,v2):
+        mesh = bpy.data.meshes.new("Retopo")
+        mesh.from_pydata([v1,v2], [(0,1)], [])
+        
+        scene = bpy.context.scene
+        mesh.update()
+        obj_new = bpy.data.objects.new("Torus", mesh)
+        scene.objects.link(obj_new)
+
+    ray = o.ray_cast
+    #ray = C.scene.ray_cast
+
+    DEBUG = False
+    def fix_point(p):
+        for d in dirs:
+            # print(p)
+            hit, no, ind = ray(p, p + d)
+            if ind != -1:
+                if DEBUG:
+                    return [p, no, None] 
+                else:
+                    # print("good", hit, no)
+                    return [hit, no, None] 
+
+        # worry!
+        print("bad!", p, BAD_NORMAL)
+        
+        return [p, BAD_NORMAL, None]
+
+    def get_points(stroke):
+        return [fix_point(point.co) for point in stroke.points]
+
+    def get_splines(gp):
+        l = None
+        for l in gp.layers:
+            if l.active: # XXX - should be layers.active
+                break
+        if l:
+            frame = l.active_frame
+            return [get_points(stroke) for stroke in frame.strokes]
+        else:
+            return []
+
+    def main():
+        scene = bpy.context.scene
+        obj = bpy.context.object
+
+        gp = None
+
+        if obj:
+            gp = obj.grease_pencil
+
+        if not gp:
+            gp = scene.grease_pencil
+            
+        if not gp:
+            self.report({'WARNING'}, "No grease pencil layer found")
+            return
+
+        splines = get_splines(gp)
+
+        for s in splines:
+            for pt in s:
+                p = pt[0]
+                n = pt[1]
+                # print(p, n)
+                if n is BAD_NORMAL:
+                    continue
+                
+                # # dont self intersect
+                best_nor = None
+                best_hit = None
+                best_dist = 10000000.0
+                pofs = p + n * 0.01
+                
+                n_seek = n * SEEK
+                m_alt_1 = RotationMatrix(radians(22.5), 3, n)
+                m_alt_2 = RotationMatrix(radians(-22.5), 3, n)
+                for _m in mats:
+                    for m in (_m, m_alt_1 * _m, m_alt_2 * _m):
+                        hit, nor, ind = ray(pofs, pofs + (m * n_seek))
+                        if ind != -1:
+                            dist = (pofs - hit).length
+                            if dist < best_dist:
+                                best_dist = dist
+                                best_nor = nor
+                                #best_hit = hit
+                
+                if best_nor:
+                    pt[1].length = best_dist
+                    best_nor.negate()
+                    pt[2] = best_nor
+
+
+                    #scene.cursor_location[:] = best_hitnyway
+                    # bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
+                    # debug_edge(p, best_hit)
+                    # p[:] = best_hit
+        
+        # Now we need to do scattering.
+        # first corners
+        hits = []
+        nors = []
+        oris = []
+        for s in splines:
+            for p,n,n_other in s: # point, normal, n_other the closest hit normal
+                if n is BAD_NORMAL:
+                    continue
+                if n_other:
+                    # cast vectors twice as long as the distance needed just incase.
+                    n_down = (n * -SEEK)
+                    l = n_down.length
+                    n_other.length = l
+                    
+                    vantage = p + n
+                    if DEBUG:
+                        p[:] = vantage
+                    
+                    # We should cast rays between n_down and n_other
+                    #for f in (0.0, 0.2, 0.4, 0.6, 0.8, 1.0):
+                    TOT = int(10 * DENSITY)
+                    #for i in list(range(TOT)):
+                    for i in list(range(TOT))[int(TOT/1.5):]: # second half
+                        f = i/(TOT-1)
+                        
+                        # focus on the center
+                        '''
+                        f -= 0.5
+                        f = f*f
+                        f += 0.5
+                        '''
+                        
+                        ntmp = f * n_down + (1.0 - f)*n_other
+                        # randomize 
+                        ntmp.x += uniform(-l, l) * RAND_LOC
+                        ntmp.y += uniform(-l, l) * RAND_LOC
+                        ntmp.z += uniform(-l, l) * RAND_LOC
+                        
+                        hit, hit_no, ind = ray(vantage, vantage + ntmp)
+                        # print(hit, hit_no)
+                        if ind != -1:
+                            if hit_no.angle(Z_UP) < WALL_LIMIT:
+                                hits.append(hit)
+                                nors.append(hit_no)
+                                oris.append(n_other.cross(hit_no))
+                                #oris.append(n_other)
+        
+        
+        
+        if 0:
+            mesh = bpy.data.meshes.new("Retopo")
+            mesh.from_pydata(hits, [], [])
+            
+            scene = bpy.context.scene
+            mesh.update()
+            obj_new = bpy.data.objects.new("Torus", mesh)
+            scene.objects.link(obj_new)
+            obj_new.layers[:] = o.layers
+            
+            # Now setup dupli-faces
+            obj_new.dupli_type = 'VERTS'
+            ob_child = bpy.data.objects["trash"]
+            ob_child.location = obj_new.location
+            ob_child.parent = obj_new
+        else:
+            
+            def apply_faces(triples):
+                # first randomize the faces
+                shuffle(triples)
+                
+                obs = group.objects[:]
+                tot = len(obs)
+                tot_div = int(len(triples) / tot)
+
+                for inst_ob in obs:
+                    triple_subset = triples[0:tot_div]
+                    triples[0:tot_div] = []
+                    
+                    vv = [tuple(v) for f in triple_subset for v in f]
+
+                    mesh = bpy.data.meshes.new("Retopo")
+                    mesh.from_pydata(vv, [], [(i*3, i*3+1, i*3+2) for i in range(len(triple_subset))])
+
+                    scene = bpy.context.scene
+                    mesh.update()
+                    obj_new = bpy.data.objects.new("Torus", mesh)
+                    scene.objects.link(obj_new)
+                    obj_new.layers[:] = o.layers
+                    

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list