General particle bug fixes + few small goodies
authorJanne Karhu <jhkarh@gmail.com>
Mon, 5 Oct 2009 13:25:56 +0000 (13:25 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Mon, 5 Oct 2009 13:25:56 +0000 (13:25 +0000)
The goodies:
* Curves can be used as normal dynamic effectors too with
  the new "curve" field shape.
* Group visualization has optional duplication counts for
  each object in the specified group.
* Object & group visualizations, which are done without
  taking the dupliobject's global position into account
  (unless the whole group is used). This is much nicer than
  the previous behavior, but I added a "Use Global Location"
  option for those who want to use it the old way.
* The active particle system's particles are now drawn a
  with theme coloured outline instead of pure white.
* Added object aligned velocity factors (buttons categorized
  and re-organized too).

Bug fixes:
* Absorption didn't work as the ui toggle button was forgotten.
* Some other force field ui tweaks.
* Crash after adding children and changing trails count.
* Display types "cross" and "axis" crashed.
* Particles weren't drawn with correct coloring.
* Billboards didn't update properly in viewport to camera
  location changes.
* Particle rotation wasn't recreated correctly from point cache.
* Changing particles amount crashed sometimes.
* Some files with child hair crashed on loading.
* Compiler warning fixes.
* Adding boids crashed on frame 1;

23 files changed:
release/scripts/ui/buttons_particle.py
release/scripts/ui/buttons_physics_common.py
source/blender/blenkernel/BKE_bvhutils.h
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/boids.c
source/blender/blenkernel/intern/bvhutils.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_intern.h
source/blender/editors/physics/physics_ops.c
source/blender/editors/space_view3d/drawobject.c
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c

index 1a800fc4dfd2b441020a6e1a73f7fc2f1cff3e02..81ddab40ec9e157bd6b62755a3df118159067f4a 100644 (file)
@@ -121,17 +121,19 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
                layout.enabled = particle_panel_enabled(psys) and not psys.multiple_caches
                
                row = layout.row()
+               row.active = part.distribution != 'GRID'
                row.itemR(part, "amount")
                
-               split = layout.split()
-               
-               col = split.column(align=True)
-               col.itemR(part, "start")
-               col.itemR(part, "end")
+               if part.type != 'HAIR':
+                       split = layout.split()
+                       
+                       col = split.column(align=True)
+                       col.itemR(part, "start")
+                       col.itemR(part, "end")
 
-               col = split.column(align=True)
-               col.itemR(part, "lifetime")
-               col.itemR(part, "random_lifetime", slider=True)
+                       col = split.column(align=True)
+                       col.itemR(part, "lifetime")
+                       col.itemR(part, "random_lifetime", slider=True)
                
                layout.row().itemL(text="Emit From:")
                
@@ -221,7 +223,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                
                point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0)
 
-class PARTICLE_PT_initial(ParticleButtonsPanel):
+class PARTICLE_PT_velocity(ParticleButtonsPanel):
        __label__ = "Velocity"
        
        def poll(self, context):
@@ -238,48 +240,66 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
                part = psys.settings
                
                layout.enabled = particle_panel_enabled(psys)
-                               
-               layout.row().itemL(text="Direction:")
        
                split = layout.split()
                        
                sub = split.column()
+               sub.itemL(text="Emitter Geometry:")
                sub.itemR(part, "normal_factor")
+               subsub = sub.column(align=True)
+               subsub.itemR(part, "tangent_factor")
+               subsub.itemR(part, "tangent_phase", slider=True)
+               
+               sub = split.column()
+               sub.itemL(text="Emitter Object")
+               sub.itemR(part, "object_aligned_factor", text="")
+                       
+               layout.row().itemL(text="Other:")
+               split = layout.split()
+               sub = split.column()
                if part.emit_from=='PARTICLE':
                        sub.itemR(part, "particle_factor")
                else:
                        sub.itemR(part, "object_factor", slider=True)
+               sub = split.column()
                sub.itemR(part, "random_factor")
-               sub.itemR(part, "tangent_factor")
-               sub.itemR(part, "tangent_phase", slider=True)
                
-               sub = split.column()
-               sub.itemL(text="TODO:")
-               sub.itemL(text="Object aligned")
-               sub.itemL(text="direction: X, Y, Z")
+               #if part.type=='REACTOR':
+               #       sub.itemR(part, "reactor_factor")
+               #       sub.itemR(part, "reaction_shape", slider=True)
                
-               if part.type=='REACTOR':
-                       sub.itemR(part, "reactor_factor")
-                       sub.itemR(part, "reaction_shape", slider=True)
+class PARTICLE_PT_rotation(ParticleButtonsPanel):
+       __label__ = "Rotation"
+       
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       psys = context.particle_system
+                       return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
                else:
-                       sub.itemL(text="")
+                       return False
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
                
-               layout.row().itemL(text="Rotation:")
-               split = layout.split()
-                       
-               sub = split.column()
+               layout.enabled = particle_panel_enabled(psys)
                
-               sub.itemR(part, "rotation_mode", text="Axis")
+               split = layout.split()
+               split.itemL(text="Initial Rotation:")
+               split.itemR(part, "rotation_dynamic")
                split = layout.split()
                        
-               sub = split.column()
-               sub.itemR(part, "rotation_dynamic")
-               sub.itemR(part, "random_rotation_factor", slider=True)
-               sub = split.column()
+               sub = split.column(align=True)
+               sub.itemR(part, "rotation_mode", text="")
+               sub.itemR(part, "random_rotation_factor", slider=True, text="Random")
+                       
+               sub = split.column(align=True)
                sub.itemR(part, "phase_factor", slider=True)
                sub.itemR(part, "random_phase_factor", text="Random", slider=True)
 
-               layout.row().itemL(text="Angular velocity:")
+               layout.row().itemL(text="Angular Velocity:")
                layout.row().itemR(part, "angular_velocity_mode", expand=True)
                split = layout.split()
                        
@@ -607,16 +627,37 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
 
                elif part.ren_as == 'OBJECT':
                        sub.itemR(part, "dupli_object")
+                       sub.itemR(part, "use_global_dupli")
                elif part.ren_as == 'GROUP':
                        sub.itemR(part, "dupli_group")
                        split = layout.split()
                        sub = split.column()
                        sub.itemR(part, "whole_group")
+                       colsub = sub.column()
+                       colsub.active = part.whole_group == False
+                       colsub.itemR(part, "use_group_count")
+                       
                        sub = split.column()
                        colsub = sub.column()
                        colsub.active = part.whole_group == False
+                       colsub.itemR(part, "use_global_dupli")
                        colsub.itemR(part, "rand_group")
                        
+                       if part.use_group_count and not part.whole_group:
+                               row = layout.row()
+                               row.template_list(part, "dupliweights", part, "active_dupliweight_index")
+                               
+                               col = row.column()
+                               subrow = col.row()
+                               subcol = subrow.column(align=True)
+                               subcol.itemO("particle.dupliob_move_up", icon='VICON_MOVE_UP', text="")
+                               subcol.itemO("particle.dupliob_move_down", icon='VICON_MOVE_DOWN', text="")
+                               
+                               weight = part.active_dupliweight
+                               if weight:
+                                       row = layout.row()
+                                       row.itemR(weight, "count")
+                       
                elif part.ren_as == 'BILLBOARD':
                        sub.itemL(text="Align:")
                        
@@ -898,7 +939,8 @@ bpy.types.register(PARTICLE_PT_particles)
 bpy.types.register(PARTICLE_PT_hair_dynamics)
 bpy.types.register(PARTICLE_PT_cache)
 bpy.types.register(PARTICLE_PT_emission)
-bpy.types.register(PARTICLE_PT_initial)
+bpy.types.register(PARTICLE_PT_velocity)
+bpy.types.register(PARTICLE_PT_rotation)
 bpy.types.register(PARTICLE_PT_physics)
 bpy.types.register(PARTICLE_PT_boidbrain)
 bpy.types.register(PARTICLE_PT_render)
index b65d092fcfa3de5d3bb4bf66bcbe71d022b45bf4..17ac1b2bbaa1157a91ae95bba49fafbd02587e93 100644 (file)
@@ -78,7 +78,7 @@ def effector_weights_ui(self, weights):
                layout.itemS()
                
                flow = layout.column_flow()
-               flow.itemR(weights, "spherical", slider=True)
+               flow.itemR(weights, "force", slider=True)
                flow.itemR(weights, "vortex", slider=True)
                flow.itemR(weights, "magnetic", slider=True)
                flow.itemR(weights, "wind", slider=True)
@@ -110,7 +110,7 @@ def basic_force_field_settings_ui(self, field):
                col.itemR(field, "flow")
        elif field.type == 'HARMONIC':
                col.itemR(field, "harmonic_damping", text="Damping")
-       elif field.type == 'VORTEX' and field.shape == 'PLANE':
+       elif field.type == 'VORTEX' and field.shape != 'POINT':
                col.itemR(field, "inflow")
        elif field.type == 'DRAG':
                col.itemR(field, "quadratic_drag", text="Quadratic")
@@ -140,6 +140,7 @@ def basic_force_field_falloff_ui(self, field):
        col.itemR(field, "z_direction", text="")
        col.itemR(field, "use_min_distance", text="Use Minimum")
        col.itemR(field, "use_max_distance", text="Use Maximum")
+       col.itemR(field, "do_absorption")
 
        col = split.column()
        col.itemR(field, "falloff_power", text="Power")
index 66c8d99959a896d7ef3c908830659f880f51b0ad..e2911a30b2580f17278a10b7e3697747fa2ebb62 100644 (file)
@@ -57,6 +57,7 @@ typedef struct BVHTreeFromMesh
 
        /* Vertex array, so that callbacks have instante access to data */
        struct MVert *vert;
+       struct MEdge *edge;             /* only used for BVHTreeFromMeshEdges */
        struct MFace *face;
 
        /* radius for raycast */
@@ -96,6 +97,8 @@ BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMes
  */
 BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
+BVHTree* bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+
 /*
  * Frees data allocated by a call to bvhtree_from_mesh_*.
  */
@@ -109,6 +112,7 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
 //Using local coordinates
 #define BVHTREE_FROM_FACES             0
 #define BVHTREE_FROM_VERTICES  1
+#define BVHTREE_FROM_EDGES             2
 
 typedef LinkNode* BVHCache;
 
index 83ec7c13946fd740df456b9655ff4296485b8b18..9a0a724ab9ae78edfefb22c95a393066efee56e0 100644 (file)
@@ -138,6 +138,7 @@ int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struc
 /* EffectedPoint->flag */
 #define PE_WIND_AS_SPEED               1
 #define PE_DYNAMIC_ROTATION            2
+#define PE_USE_NORMAL_DATA             4
 
 /* EffectorData->flag */
 #define PE_VELOCITY_TO_IMPULSE 1
index e0259ff10dd3437c45e5284fb884e1116d021fc8..e9285782a1e4aab19408d6cabbc54243b6523cfa 100644 (file)
@@ -201,6 +201,8 @@ struct Object *psys_get_lattice(struct ParticleSimulationData *sim);
 int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
 int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
 
+void psys_check_group_weights(struct ParticleSettings *part);
+
 /* free */
 void psys_free_settings(struct ParticleSettings *part);
 void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
index bd779935d553bd3d3d2c8b7d6d970b3515588adf..5cd901066f89f793e7a7392cce7696f6bd669bbe 100644 (file)
@@ -776,6 +776,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
        GroupObject *go;
        Object *ob=0, **oblist=0, obcopy, *obcopylist=0;
        DupliObject *dob;
+       ParticleDupliWeight *dw;
        ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)};
        ParticleSettings *part;
        ParticleData *pa;
@@ -783,7 +784,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
        ParticleKey state;
        ParticleCacheKey *cache;
        float ctime, pa_time, scale = 1.0f;
-       float tmat[4][4], mat[4][4], pamat[4][4], size=0.0;
+       float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0;
        float (*obmat)[4], (*oldobmat)[4];
        int lay, a, b, counter, hair = 0;
        int totpart, totchild, totgroup=0, pa_num;
@@ -813,6 +814,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                ((part->ren_as == PART_DRAW_OB && part->dup_ob) ||
                (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) {
 
+               psys_check_group_weights(part);
+
                /* if we have a hair particle system, use the path cache */
                if(part->type == PART_HAIR) {
                        if(psys->flag & PSYS_HAIR_DONE)
@@ -831,18 +834,37 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                if(part->ren_as==PART_DRAW_GR) {
                        group_handle_recalc_and_update(scene, par, part->dup_group);
 
-                       for(go=part->dup_group->gobject.first; go; go=go->next)
-                               totgroup++;
+                       if(part->draw & PART_DRAW_COUNT_GR) {
+                               for(dw=part->dupliweights.first; dw; dw=dw->next)
+                                       totgroup += dw->count;
+                       }
+                       else {
+                               for(go=part->dup_group->gobject.first; go; go=go->next)
+                                       totgroup++;
+                       }
 
                        /* we also copy the actual objects to restore afterwards, since
                         * where_is_object_time will change the object which breaks transform */
                        oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
                        obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list");
 
-                       go = part->dup_group->gobject.first;
-                       for(a=0; a<totgroup; a++, go=go->next) {
-                               oblist[a] = go->ob;
-                               obcopylist[a] = *go->ob;
+                       
+                       if(part->draw & PART_DRAW_COUNT_GR && totgroup) {
+                               dw = part->dupliweights.first;
+
+                               for(a=0; a<totgroup; dw=dw->next) {
+                                       for(b=0; b<dw->count; b++, a++) {
+                                               oblist[a] = dw->ob;
+                                               obcopylist[a] = *dw->ob;
+                                       }
+                               }
+                       }
+                       else {
+                               go = part->dup_group->gobject.first;
+                               for(a=0; a<totgroup; a++, go=go->next) {
+                                       oblist[a] = go->ob;
+                                       obcopylist[a] = *go->ob;
+                               }
                        }
                }
                else {
@@ -936,11 +958,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                        else {
                                /* to give ipos in object correct offset */
                                where_is_object_time(scene, ob, ctime-pa_time);
+
+                               VECCOPY(vec, obmat[3]);
+                               obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
                                
                                Mat4CpyMat4(mat, pamat);
 
                                Mat4MulMat4(tmat, obmat, mat);
                                Mat4MulFloat3((float *)tmat, size*scale);
+
+                               if(part->draw & PART_DRAW_GLOBAL_OB)
+                                       VECADD(tmat[3], tmat[3], vec);
+
                                if(par_space_mat)
                                        Mat4MulMat4(mat, tmat, par_space_mat);
                                else
index 76824d3a34a5bfd78c376d146687d1e8d41690e3..712fb13cfc08b053dd5a222836bb93d15ffa31f0 100644 (file)
@@ -73,13 +73,11 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
 {
        BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
        BoidSettings *boids = bbd->part->boids;
-       Object *priority_ob = NULL;
        BoidParticle *bpa = pa->boid;
        EffectedPoint epoint;
        ListBase *effectors = bbd->sim->psys->effectors;
        EffectorCache *cur, *eff = NULL;
        EffectorData efd, cur_efd;
-       float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
        float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
        float priority = 0.0f, len = 0.0f;
        int ret = 0;
@@ -1051,9 +1049,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
        float wanted_dir[3];
        float q[4], mat[3][3]; /* rotation */
        float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
-       float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f};
+       float force[3] = {0.0f, 0.0f, 0.0f};
        float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;
-       int p = pa - bbd->sim->psys->particles;
 
        set_boid_values(&val, boids, pa);
 
index d9e005811d0078e16ca68d75d86331c87566dbf3..f2526231d5024b3453d279991e786b20232a9977 100644 (file)
@@ -479,6 +479,32 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
        } while(t2);
 }
 
+// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
+// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
+static void mesh_edges_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest)
+{
+       const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
+       MVert *vert     = data->vert;
+       MEdge *edge = data->edge + index;
+       float nearest_tmp[3], dist;
+
+       float *t0, *t1;
+       t0 = vert[ edge->v1 ].co;
+       t1 = vert[ edge->v2 ].co;
+       
+       PclosestVL3Dfl(nearest_tmp, co, t0, t1);
+       dist = VecLenf(nearest_tmp, co);
+       
+       if(dist < nearest->dist)
+       {
+               nearest->index = index;
+               nearest->dist = dist;
+               VECCOPY(nearest->co, nearest_tmp);
+               VecSubf(nearest->no, t0, t1);
+               Normalize(nearest->no);
+       }
+}
+
 /*
  * BVH builders
  */
@@ -605,6 +631,68 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
 
 }
 
+// Builds a bvh tree.. where nodes are the faces of the given mesh.
+BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+{
+       BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES);
+
+       //Not in cache
+       if(tree == NULL)
+       {
+               int i;
+               int numEdges= mesh->getNumEdges(mesh);
+               MVert *vert     = mesh->getVertDataArray(mesh, CD_MVERT);
+               MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
+
+               if(vert != NULL && edge != NULL)
+               {
+                       /* Create a bvh-tree of the given target */
+                       tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
+                       if(tree != NULL)
+                       {
+                               for(i = 0; i < numEdges; i++)
+                               {
+                                       float co[4][3];
+                                       VECCOPY(co[0], vert[ edge[i].v1 ].co);
+                                       VECCOPY(co[1], vert[ edge[i].v2 ].co);
+                       
+                                       BLI_bvhtree_insert(tree, i, co[0], 2);
+                               }
+                               BLI_bvhtree_balance(tree);
+
+                               //Save on cache for later use
+//                             printf("BVHTree built and saved on cache\n");
+                               bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES);
+                       }
+               }
+       }
+       else
+       {
+//             printf("BVHTree is already build, using cached tree\n");
+       }
+
+
+       //Setup BVHTreeFromMesh
+       memset(data, 0, sizeof(*data));
+       data->tree = tree;
+
+       if(data->tree)
+       {
+               data->cached = TRUE;
+
+               data->nearest_callback = mesh_edges_nearest_point;
+               data->raycast_callback = NULL;
+
+               data->mesh = mesh;
+               data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
+               data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
+
+               data->sphere_radius = epsilon;
+       }
+       return data->tree;
+
+}
+
 // Frees data allocated by a call to bvhtree_from_mesh_*.
 void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
 {
index 7cc65de827aa3b51767c4e80ae8d6d630480e818..9b648e2c05c1adb8115414ed86df7da1df461187 100644 (file)
@@ -228,6 +228,8 @@ static void precalculate_effector(EffectorCache *eff)
        }
        else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) {
                eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface );
+               if(eff->ob->type == OB_CURVE)
+                       eff->flag |= PE_USE_NORMAL_DATA;
        }
        else if(eff->psys)
                psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
@@ -518,7 +520,7 @@ float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *poi
        float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
        float fac, r_fac;
 
-       fac = Inpf(efd->nor, efd->vec_to_point);
+       fac = Inpf(efd->nor, efd->vec_to_point2);
 
        if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f)
                falloff=0.0f;
@@ -691,10 +693,16 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
                VecSubf(efd->vec_to_point, point->loc, efd->loc);
                efd->distance = VecLength(efd->vec_to_point);
 
-               /* for some effectors we need the object center every time */
-               VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
-               VECCOPY(efd->nor2, eff->ob->obmat[2]);
-               Normalize(efd->nor2);
+               if(eff->flag & PE_USE_NORMAL_DATA) {
+                       VECCOPY(efd->vec_to_point2, efd->vec_to_point);
+                       VECCOPY(efd->nor2, efd->nor);
+               }
+               else {
+                       /* for some effectors we need the object center every time */
+                       VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
+                       VECCOPY(efd->nor2, eff->ob->obmat[2]);
+                       Normalize(efd->nor2);
+               }
        }
 
        return ret;
@@ -835,8 +843,7 @@ void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *
 
        switch(pd->forcefield){
                case PFIELD_WIND:
-                       Normalize(force);
-                       strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f);
+                       VECCOPY(force, efd->nor);
                        VecMulf(force, strength * efd->falloff);
                        break;
                case PFIELD_FORCE:
index 3b47c2f18305a2c8c0d8ad263e349a2f372f3661..55fb9f45bb36eb9fe4cb0510ad78100f7bfbef4b 100644 (file)
@@ -6211,7 +6211,8 @@ static void surfaceModifier_freeData(ModifierData *md)
                        MEM_freeN(surmd->bvhtree);
                }
 
-               surmd->dm->release(surmd->dm);
+               if(surmd->dm)
+                       surmd->dm->release(surmd->dm);
 
                if(surmd->x)
                        MEM_freeN(surmd->x);
@@ -6298,7 +6299,10 @@ static void surfaceModifier_deformVerts(
                else
                        surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
 
-               bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+               if(surmd->dm->getNumFaces(surmd->dm))
+                       bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+               else
+                       bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
        }
 }
 
index f4f5a1364a303121a1b16543907119d159bd68ac..011d5c3f1342c862921fc40c260b6b6913d223dd 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "DNA_scene_types.h"
 #include "DNA_boid_types.h"
+#include "DNA_group_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -63,6 +64,7 @@
 #include "BKE_cloth.h"
 #include "BKE_effect.h"
 #include "BKE_global.h"
+#include "BKE_group.h"
 #include "BKE_main.h"
 #include "BKE_lattice.h"
 #include "BKE_utildefines.h"
@@ -296,6 +298,60 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
        return 1;
 }
 
+void psys_check_group_weights(ParticleSettings *part)
+{
+       ParticleDupliWeight *dw, *tdw;
+       GroupObject *go;
+       int current = 0;
+
+       if(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
+               /* first remove all weights that don't have an object in the group */
+               dw = part->dupliweights.first;
+               while(dw) {
+                       if(!object_in_group(dw->ob, part->dup_group)) {
+                               tdw = dw->next;
+                               BLI_freelinkN(&part->dupliweights, dw);
+                               dw = tdw;
+                       }
+                       else
+                               dw = dw->next;
+               }
+
+               /* then add objects in the group to new list */
+               go = part->dup_group->gobject.first;
+               while(go) {
+                       dw = part->dupliweights.first;
+                       while(dw && dw->ob != go->ob)
+                               dw = dw->next;
+                       
+                       if(!dw) {
+                               dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
+                               dw->ob = go->ob;
+                               dw->count = 1;
+                               BLI_addtail(&part->dupliweights, dw);
+                       }
+
+                       go = go->next;  
+               }
+
+               dw = part->dupliweights.first;
+               for(; dw; dw=dw->next) {
+                       if(dw->flag & PART_DUPLIW_CURRENT) {
+                               current = 1;
+                               break;
+                       }
+               }
+
+               if(!current) {
+                       dw = part->dupliweights.first;
+                       if(dw)
+                               dw->flag |= PART_DUPLIW_CURRENT;
+               }
+       }
+       else {
+               BLI_freelistN(&part->dupliweights);
+       }
+}
 /************************************************/
 /*                     Freeing stuff                                           */
 /************************************************/
@@ -307,6 +363,8 @@ void psys_free_settings(ParticleSettings *part)
        if(part->effector_weights)
                MEM_freeN(part->effector_weights);
 
+       BLI_freelistN(&part->dupliweights);
+
        boid_free_settings(part->boids);
 }
 
@@ -439,6 +497,9 @@ void psys_free_pdd(ParticleSystem *psys)
                if(psys->pdd->vedata)
                        MEM_freeN(psys->pdd->vedata);
                psys->pdd->vedata = NULL;
+
+               psys->pdd->totpoint = 0;
+               psys->pdd->tot_vec_size = 0;
        }
 }
 /* free everything */
@@ -2047,10 +2108,10 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float
        float roughfac;
 
        roughfac=fac*(float)pow((double)t,shape);
-       VECCOPY(rough,loc);
+       Vec2Copyf(rough,loc);
        rough[0]=-1.0f+2.0f*rough[0];
        rough[1]=-1.0f+2.0f*rough[1];
-       VecMulf(rough,roughfac);
+       Vec2Mulf(rough,roughfac);
 
        VECADDFAC(state->co,state->co,mat[0],rough[0]);
        VECADDFAC(state->co,state->co,mat[1],rough[1]);
@@ -3235,6 +3296,9 @@ static void default_particle_settings(ParticleSettings *part)
        part->size=0.05;
        part->childsize=1.0;
 
+       part->rotmode = PART_ROT_VEL;
+       part->avemode = PART_AVE_SPIN;
+
        part->child_nbr=10;
        part->ren_child_nbr=100;
        part->childrad=0.2f;
@@ -3788,6 +3852,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                
                /* get different child parameters from textures & vgroups */
                memset(&ctx, 0, sizeof(ParticleThreadContext));
+               ctx.sim = *sim;
                ctx.dm = psmd->dm;
                ctx.ma = ma;
                /* TODO: assign vertex groups */
@@ -3856,6 +3921,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
        ChildParticle *cpa = NULL;
        float cfra;
        int totpart = psys->totpart;
+       float timestep = psys_get_timestep(sim);
 
        /* negative time means "use current time" */
        cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0);
@@ -3924,13 +3990,14 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
                                calc_latt_deform(sim->psys->lattice, state->co,1.0f);
                }
                else{
-                       if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
+                       if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
+                               || pa->prev_state.time <= 0.0f)
                                copy_particle_key(state, &pa->state, 1);
                        else if(pa->prev_state.time==state->time)
                                copy_particle_key(state, &pa->prev_state, 1);
                        else {
                                /* let's interpolate to try to be as accurate as possible */
-                               if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) {
+                               if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) {
                                        ParticleKey keys[4];
                                        float dfra, keytime, frs_sec = sim->scene->r.frs_sec;
 
@@ -3949,13 +4016,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
                                                keytime = (state->time - keys[1].time) / dfra;
 
                                                /* convert velocity to timestep size */
-                                               VecMulf(keys[1].vel, dfra / frs_sec);
-                                               VecMulf(keys[2].vel, dfra / frs_sec);
+                                               VecMulf(keys[1].vel, dfra * timestep);
+                                               VecMulf(keys[2].vel, dfra * timestep);
                                                
                                                psys_interpolate_particle(-1, keys, keytime, state, 1);
                                                
                                                /* convert back to real velocity */
-                                               VecMulf(state->vel, frs_sec / dfra);
+                                               VecMulf(state->vel, 1.0f / (dfra * timestep));
 
                                                VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime);
                                                QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime);
index d757372f17bed8187cebbf55f10dd1ffb833f248..45050127582fb732a916cdb5a7a57c00aef5dd68 100644 (file)
@@ -183,6 +183,8 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
 
        if(totpart && totpart != psys->totpart) {
                newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
+               if(psys->part->phystype == PART_PHYS_BOIDS)
+                       newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
        
                if(psys->particles) {
                        totsaved=MIN2(psys->totpart,totpart);
@@ -215,13 +217,12 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
                }
                
                psys->particles=newpars;
+               psys->totpart=totpart;
 
                if(newboids) {
                        LOOP_PARTICLES
                                pa->boid = newboids++;
                }
-               
-               psys->totpart=totpart;
        }
 
        if(psys->child) {
@@ -1660,7 +1661,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
        ParticleKey state;
        //IpoCurve *icu=0; // XXX old animation system
        float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
-       float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
+       float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0};
        float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
        float q_phase[4], r_phase;
        int p = pa - psys->particles;
@@ -1773,7 +1774,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
                }
        }
 
-       if(part->phystype==PART_PHYS_BOIDS) {
+       if(part->phystype==PART_PHYS_BOIDS && pa->boid) {
                BoidParticle *bpa = pa->boid;
                float dvec[3], q[4], mat[3][3];
 
@@ -1839,6 +1840,23 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
                        VECADDFAC(vel,vel,vtan,part->tanfac);
                        //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f));
 
+               /*              *emitter object orientation             */
+               if(part->ob_vel[0]!=0.0) {
+                       VECCOPY(vec, ob->obmat[0]);
+                       Normalize(vec);
+                       VECADDFAC(vel, vel, vec, part->ob_vel[0]);
+               }
+               if(part->ob_vel[1]!=0.0) {
+                       VECCOPY(vec, ob->obmat[1]);
+                       Normalize(vec);
+                       VECADDFAC(vel, vel, vec, part->ob_vel[1]);
+               }
+               if(part->ob_vel[2]!=0.0) {
+                       VECCOPY(vec, ob->obmat[2]);
+                       Normalize(vec);
+                       VECADDFAC(vel, vel, vec, part->ob_vel[2]);
+               }
+
                /*              *texture                                                */
                /* TODO */
 
@@ -3135,7 +3153,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part=psys->part;
        KDTree *tree=0;
-       //IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
+       //IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
 /*     Material *ma=give_current_material(sim->ob, part->omat); */
        BoidBrainData bbd;
        PARTICLE_P;
index bffe4566f74384e34ed2a396c53543d796337ec7..fa0d5cba604bd9bfa54f9708da5db135fcc93ee7 100644 (file)
@@ -269,7 +269,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
 
        /* determine rotation from velocity */
        if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
-               vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
+               vectoquat(pa->state.vel, OB_NEGX, OB_POSZ, pa->state.rot);
        }
 }
 static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
@@ -292,6 +292,23 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
        else
                BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
 
+       /* determine velocity from previous location */
+       if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
+               if(keys[1].time > keys[2].time) {
+                       VecSubf(keys[2].vel, keys[1].co, keys[2].co);
+                       VecMulf(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec);
+               }
+               else {
+                       VecSubf(keys[2].vel, keys[2].co, keys[1].co);
+                       VecMulf(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec);
+               }
+       }
+
+       /* determine rotation from velocity */
+       if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
+               vectoquat(keys[2].vel, OB_NEGX, OB_POSZ, keys[2].rot);
+       }
+
        if(cfra > pa->time)
                cfra1 = MAX2(cfra1, pa->time);
 
@@ -301,7 +318,7 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
        VecMulf(keys[2].vel, dfra / frs_sec);
 
        psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
-       QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
+       QuatInterpol(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
 
        VecMulf(pa->state.vel, frs_sec / dfra);
 
@@ -594,7 +611,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
        if(psys->part->phystype == PART_PHYS_BOIDS)
                pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
 
-       if(psys->part->rotmode || psys->part->avemode)
+       if(psys->part->rotmode!=PART_ROT_VEL
+               || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
                pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
 
        if(psys->part->flag & PART_ROT_DYN)
index a3a56e9a07530e00c941b4eda3d464d8cc51afe7..989e2b3fa9e506a991d1537a9e6ce239486f54df 100644 (file)
@@ -3033,6 +3033,7 @@ static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointC
 static void lib_link_particlesettings(FileData *fd, Main *main)
 {
        ParticleSettings *part;
+       ParticleDupliWeight *dw;
 
        part= main->particle.first;
        while(part) {
@@ -3048,6 +3049,10 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
                        if(part->effector_weights)
                                part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
 
+                       dw = part->dupliweights.first;
+                       for(; dw; dw=dw->next)
+                               dw->ob = newlibadr(fd, part->id.lib, dw->ob);
+
                        if(part->boids) {
                                BoidState *state = part->boids->states.first;
                                BoidRule *rule;
@@ -3088,6 +3093,8 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        else
                part->effector_weights = BKE_add_effector_weights(part->eff_group);
 
+       link_list(fd, &part->dupliweights);
+
        part->boids= newdataadr(fd, part->boids);
 
        if(part->boids) {
index 1f46446dc2a830925e40b97d46bcfc276bcb9cae..c92c0909d3bd02bd92ca51dde43d6e6c6991b085 100644 (file)
@@ -610,6 +610,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
 static void write_particlesettings(WriteData *wd, ListBase *idbase)
 {
        ParticleSettings *part;
+       ParticleDupliWeight *dw;
 
        part= idbase->first;
        while(part) {
@@ -622,6 +623,10 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
                        writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
 
+                       dw = part->dupliweights.first;
+                       for(; dw; dw=dw->next)
+                               writestruct(wd, DATA, "ParticleDupliWeight", 1, dw);
+
                        if(part->boids && part->phystype == PART_PHYS_BOIDS) {
                                BoidState *state = part->boids->states.first;
 
index cef630b67110ff8eeedd1fada8ff05dc3c1d2e2d..1dc08a162b75546a59b395b2e7f69b6f5c8427d9 100644 (file)
@@ -348,6 +348,82 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/************************ move up particle dupliweight operator *********************/
+
+static int dupliob_move_up_exec(bContext *C, wmOperator *op)
+{
+       PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+       ParticleSystem *psys= ptr.data;
+       ParticleSettings *part;
+       ParticleDupliWeight *dw;
+
+       if(!psys)
+               return OPERATOR_CANCELLED;
+
+       part = psys->part;
+       for(dw=part->dupliweights.first; dw; dw=dw->next) {
+               if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
+                       BLI_remlink(&part->dupliweights, dw);
+                       BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
+
+                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+                       break;
+               }
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
+{
+       ot->name= "Move Up Dupli Object";
+       ot->idname= "PARTICLE_OT_dupliob_move_up";
+       ot->description= "Move dupli object up in the list.";
+       
+       ot->exec= dupliob_move_up_exec;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ move down particle dupliweight operator *********************/
+
+static int dupliob_move_down_exec(bContext *C, wmOperator *op)
+{
+       PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+       ParticleSystem *psys= ptr.data;
+       ParticleSettings *part;
+       ParticleDupliWeight *dw;
+
+       if(!psys)
+               return OPERATOR_CANCELLED;
+
+       part = psys->part;
+       for(dw=part->dupliweights.first; dw; dw=dw->next) {
+               if(dw->flag & PART_DUPLIW_CURRENT && dw->next) {
+                       BLI_remlink(&part->dupliweights, dw);
+                       BLI_insertlink(&part->dupliweights, dw->next, dw);
+
+                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+                       break;
+               }
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
+{
+       ot->name= "Move Down Dupli Object";
+       ot->idname= "PARTICLE_OT_dupliob_move_down";
+       ot->description= "Move dupli object down in the list.";
+       
+       ot->exec= dupliob_move_down_exec;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /************************ connect/disconnect hair operators *********************/
 
 static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
index 956f26c478dd020a591a082bd39fbb77559fa7cf..3847ec8032a3b274636334224275e942a658b9fa 100644 (file)
@@ -77,6 +77,9 @@ void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
 void PARTICLE_OT_connect_hair(struct wmOperatorType *ot);
 void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot);
 
+void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot);
+void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot);
+
 /* particle_boids.c */
 void BOID_OT_rule_add(struct wmOperatorType *ot);
 void BOID_OT_rule_del(struct wmOperatorType *ot);
index a62d3d8fd78237e3cbf0ea90f427c215bb3c869a..ddc5fb9c9b6d2cf43074494b90896def360f35e1 100644 (file)
@@ -78,6 +78,9 @@ static void operatortypes_particle(void)
        WM_operatortype_append(PARTICLE_OT_target_move_down);
        WM_operatortype_append(PARTICLE_OT_connect_hair);
        WM_operatortype_append(PARTICLE_OT_disconnect_hair);
+
+       WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
+       WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
 }
 
 static void keymap_particle(wmWindowManager *wm)
index 0f2a57d881c5a126d3966f46e8e69dabfedb0002..0659b5cfd1156a21743460d5b3e4caa0595ee69f 100644 (file)
@@ -3358,7 +3358,30 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
 }
 
 /* *********** drawing for particles ************* */
+static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
+{
+       /* draw created data arrays */
+       switch(draw_as){
+               case PART_DRAW_AXIS:
+               case PART_DRAW_CROSS:
+                       glDrawArrays(GL_LINES, 0, 6*totpoint);
+                       break;
+               case PART_DRAW_LINE:
+                       glDrawArrays(GL_LINES, 0, 2*totpoint);
+                       break;
+               case PART_DRAW_BB:
+                       if(ob_dt<=OB_WIRE || select)
+                               glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+                       else
+                               glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
 
+                       glDrawArrays(GL_QUADS, 0, 4*totpoint);
+                       break;
+               default:
+                       glDrawArrays(GL_POINTS, 0, totpoint);
+                       break;
+       }
+}
 static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
 {
        float vec[3], vec2[3];
@@ -3401,7 +3424,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
                                cd[7]=cd[10]=1.0;
                                cd[13]=cd[12]=cd[15]=cd[16]=0.0;
                                cd[14]=cd[17]=1.0;
-                               cd+=18;
+                               pdd->cd+=18;
 
                                VECCOPY(vec2,state->co);
                        }
@@ -3552,7 +3575,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
        if(psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART)==0)
                return;
                
-       if(part->draw_as==PART_DRAW_NOT) return;
+       if(part->draw_as == PART_DRAW_REND)
+               draw_as = part->ren_as;
+       else
+               draw_as = part->draw_as;
+
+       if(draw_as == PART_DRAW_NOT)
+               return;
 
 /* 2. */
        sim.psmd = psmd = psys_get_modifier(ob,psys);
@@ -3582,26 +3611,22 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        if(v3d->zbuf) glDepthMask(1);
 
-       if(select)
-               cpack(0xFFFFFF);
-       else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
+       if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
                glColor3f(ma->r,ma->g,ma->b);
 
                ma_r = ma->r;
                ma_g = ma->g;
                ma_b = ma->b;
-
-               if(pdd) {
-                       pdd->ma_r = &ma_r;
-                       pdd->ma_g = &ma_g;
-                       pdd->ma_b = &ma_b;
-               }
-
-               create_cdata = 1;
        }
        else
                cpack(0);
 
+       if(pdd) {
+               pdd->ma_r = &ma_r;
+               pdd->ma_g = &ma_g;
+               pdd->ma_b = &ma_b;
+       }
+
        timestep= psys_get_timestep(&sim);
 
        if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
@@ -3612,11 +3637,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        totpart=psys->totpart;
 
-       if(part->draw_as==PART_DRAW_REND)
-               draw_as = part->ren_as;
-       else
-               draw_as = part->draw_as;
-
        //if(part->flag&PART_GLOB_TIME)
        cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
 
@@ -3646,6 +3666,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                                pixsize*=2.0;
                        else
                                pixsize*=part->draw_size;
+
+                       if(draw_as==PART_DRAW_AXIS)
+                               create_cdata = 1;
                        break;
                case PART_DRAW_OB:
                        if(part->dup_ob==0)
@@ -3693,9 +3716,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                Normalize(imat[1]);
        }
 
+       if(!create_cdata && pdd && pdd->cdata) {
+               MEM_freeN(pdd->cdata);
+               pdd->cdata = pdd->cd = NULL;
+       }
+
 /* 4. */
-       if(draw_as && draw_as!=PART_DRAW_PATH) {
+       if(draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC)==0) {
                int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+               int create_ndata = 0;
 
                if(!pdd)
                        pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData");
@@ -3705,37 +3734,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                        psys_make_temp_pointcache(ob, psys);
                }
 
+               switch(draw_as) {
+                       case PART_DRAW_AXIS:
+                       case PART_DRAW_CROSS:
+                               tot_vec_size *= 6;
+                               if(draw_as != PART_DRAW_CROSS)
+                                       create_cdata = 1;
+                               break;
+                       case PART_DRAW_LINE:
+                               tot_vec_size *= 2;
+                               break;
+                       case PART_DRAW_BB:
+                               tot_vec_size *= 4;
+                               create_ndata = 1;
+                               break;
+               }
+
                if(pdd->tot_vec_size != tot_vec_size)
                        psys_free_pdd(psys);
 
-               if(draw_as!=PART_DRAW_CIRC) {
-                       switch(draw_as) {
-                               case PART_DRAW_AXIS:
-                               case PART_DRAW_CROSS:
-                                       if(draw_as != PART_DRAW_CROSS || create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
-                                       break;
-                               case PART_DRAW_LINE:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
-                                       break;
-                               case PART_DRAW_BB:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
-                                       if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
-                                       break;
-                               default:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata");
-                       }
-               }
+               if(!pdd->vdata)
+                       pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
+               if(create_cdata && !pdd->cdata)
+                       pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
+               if(create_ndata && !pdd->ndata)
+                       pdd->ndata = MEM_callocN(tot_vec_size, "particle_vdata");
 
                if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
-                       if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
+                       if(!pdd->vedata)
+                               pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
+
                        need_v = 1;
                }
 
@@ -3744,11 +3772,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                pdd->cd= pdd->cdata;
                pdd->nd= pdd->ndata;
                pdd->tot_vec_size= tot_vec_size;
-
-               psys->lattice= psys_get_lattice(&sim);
        }
 
-       if(draw_as){
+       psys->lattice= psys_get_lattice(&sim);
+
+       if(draw_as!=PART_DRAW_PATH){
 /* 5. */
                if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED)
                        && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) {
@@ -3836,156 +3864,139 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                                r_length = PSYS_FRAND(a + 22);
                        }
 
-                       if(draw_as!=PART_DRAW_PATH){
-                               drawn = 0;
-                               if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
-                                       float length = part->path_end * (1.0 - part->randlength * r_length);
-                                       int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
-                                       float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
-                                       float dt = length / (trail_count ? (float)trail_count : 1.0f);
-                                       int i=0;
-
-                                       ct+=dt;
-                                       for(i=0; i < trail_count; i++, ct += dt) {
-                                               if(part->draw & PART_ABS_PATH_TIME) {
-                                                       if(ct < pa_birthtime || ct > pa_dietime)
-                                                               continue;
-                                               }
-                                               else if(ct < 0.0f || ct > 1.0f)
+                       drawn = 0;
+                       if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
+                               float length = part->path_end * (1.0 - part->randlength * r_length);
+                               int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
+                               float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
+                               float dt = length / (trail_count ? (float)trail_count : 1.0f);
+                               int i=0;
+
+                               ct+=dt;
+                               for(i=0; i < trail_count; i++, ct += dt) {
+                                       if(part->draw & PART_ABS_PATH_TIME) {
+                                               if(ct < pa_birthtime || ct > pa_dietime)
                                                        continue;
+                                       }
+                                       else if(ct < 0.0f || ct > 1.0f)
+                                               continue;
 
-                                               state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
-                                               psys_get_particle_on_path(&sim,a,&state,need_v);
-                                               
-                                               if(psys->parent)
-                                                       Mat4MulVecfl(psys->parent->obmat, state.co);
-
-                                               /* create actiual particle data */
-                                               if(draw_as == PART_DRAW_BB) {
-                                                       bb.size = pa_size;
-                                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
-                                                       bb.time = ct;
-                                               }
+                                       state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
+                                       psys_get_particle_on_path(&sim,a,&state,need_v);
+                                       
+                                       if(psys->parent)
+                                               Mat4MulVecfl(psys->parent->obmat, state.co);
+
+                                       /* create actiual particle data */
+                                       if(draw_as == PART_DRAW_BB) {
+                                               bb.size = pa_size;
+                                               bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                               bb.time = ct;
+                                       }
 
-                                               draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
+                                       draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
 
-                                               totpoint++;
-                                               drawn = 1;
-                                       }
+                                       totpoint++;
+                                       drawn = 1;
                                }
-                               else
-                               {
-                                       state.time=cfra;
-                                       if(psys_get_particle_state(&sim,a,&state,0)){
-                                               if(psys->parent)
-                                                       Mat4MulVecfl(psys->parent->obmat, state.co);
-
-                                               /* create actiual particle data */
-                                               if(draw_as == PART_DRAW_BB) {
-                                                       bb.size = pa_size;
-                                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
-                                                       bb.time = pa_time;
-                                               }
+                       }
+                       else
+                       {
+                               state.time=cfra;
+                               if(psys_get_particle_state(&sim,a,&state,0)){
+                                       if(psys->parent)
+                                               Mat4MulVecfl(psys->parent->obmat, state.co);
+
+                                       /* create actiual particle data */
+                                       if(draw_as == PART_DRAW_BB) {
+                                               bb.size = pa_size;
+                                               bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                               bb.time = pa_time;
+                                       }
 
-                                               draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
+                                       draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
 
-                                               totpoint++;
-                                               drawn = 1;
-                                       }
+                                       totpoint++;
+                                       drawn = 1;
                                }
+                       }
 
-                               if(drawn) {
-                                       /* additional things to draw for each particle  */
-                                       /* (velocity, size and number)                                  */
-                                       if(pdd->vedata){
-                                               VECCOPY(pdd->ved,state.co);
-                                               pdd->ved+=3;
-                                               VECCOPY(vel,state.vel);
-                                               VecMulf(vel,timestep);
-                                               VECADD(pdd->ved,state.co,vel);
-                                               pdd->ved+=3;
-
-                                               totve++;
-                                       }
+                       if(drawn) {
+                               /* additional things to draw for each particle  */
+                               /* (velocity, size and number)                                  */
+                               if(pdd->vedata){
+                                       VECCOPY(pdd->ved,state.co);
+                                       pdd->ved+=3;
+                                       VECCOPY(vel,state.vel);
+                                       VecMulf(vel,timestep);
+                                       VECADD(pdd->ved,state.co,vel);
+                                       pdd->ved+=3;
+
+                                       totve++;
+                               }
 
-                                       if(part->draw & PART_DRAW_SIZE){
-                                               setlinestyle(3);
-                                               drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
-                                               setlinestyle(0);
-                                       }
+                               if(part->draw & PART_DRAW_SIZE){
+                                       setlinestyle(3);
+                                       drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+                                       setlinestyle(0);
+                               }
 
-                                       if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
-                                               val[0]= '\0';
-                                               
-                                               if(part->draw&PART_DRAW_NUM)
-                                                       sprintf(val, " %i", a);
+                               if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
+                                       val[0]= '\0';
+                                       
+                                       if(part->draw&PART_DRAW_NUM)
+                                               sprintf(val, " %i", a);
 
-                                               if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
-                                                       sprintf(val, "%s:", val);
+                                       if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
+                                               sprintf(val, "%s:", val);
 
-                                               if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
-                                                       sprintf(val, "%s %.2f", val, pa_health);
+                                       if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
+                                               sprintf(val, "%s %.2f", val, pa_health);
 
-                                               /* in path drawing state.co is the end point */
-                                               view3d_cached_text_draw_add(state.co[0],  state.co[1],  state.co[2], val, 0);
-                                       }
+                                       /* in path drawing state.co is the end point */
+                                       view3d_cached_text_draw_add(state.co[0],  state.co[1],  state.co[2], val, 0);
                                }
                        }
                }
+       }
 /* 6. */
 
-               glGetIntegerv(GL_POLYGON_MODE, polygonmode);
-               glDisableClientState(GL_NORMAL_ARRAY);
-
-               if(draw_as==PART_DRAW_PATH){
-                       ParticleCacheKey **cache, *path;
-                       float *cd2=0,*cdata2=0;
-
-                       glEnableClientState(GL_VERTEX_ARRAY);
+       glGetIntegerv(GL_POLYGON_MODE, polygonmode);
+       glDisableClientState(GL_NORMAL_ARRAY);
 
-                       /* setup gl flags */
-                       if(ob_dt > OB_WIRE) {
-                               glEnableClientState(GL_NORMAL_ARRAY);
+       if(draw_as==PART_DRAW_PATH){
+               ParticleCacheKey **cache, *path;
+               float *cd2=0,*cdata2=0;
 
-                               if(part->draw&PART_DRAW_MAT_COL)
-                                       glEnableClientState(GL_COLOR_ARRAY);
+               glEnableClientState(GL_VERTEX_ARRAY);
 
-                               glEnable(GL_LIGHTING);
-                               glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-                               glEnable(GL_COLOR_MATERIAL);
-                       }
-                       else {
-                               glDisableClientState(GL_NORMAL_ARRAY);
+               /* setup gl flags */
+               if(ob_dt > OB_WIRE) {
+                       glEnableClientState(GL_NORMAL_ARRAY);
 
-                               glDisable(GL_COLOR_MATERIAL);
-                               glDisable(GL_LIGHTING);
-                               UI_ThemeColor(TH_WIRE);
-                       }
+                       if(part->draw&PART_DRAW_MAT_COL)
+                               glEnableClientState(GL_COLOR_ARRAY);
 
-                       if(totchild && (part->draw&PART_DRAW_PARENT)==0)
-                               totpart=0;
+                       glEnable(GL_LIGHTING);
+                       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                       glEnable(GL_COLOR_MATERIAL);
+               }
+               else {
+                       glDisableClientState(GL_NORMAL_ARRAY);
 
-                       /* draw actual/parent particles */
-                       cache=psys->pathcache;
-                       for(a=0, pa=psys->particles; a<totpart; a++, pa++){
-                               path=cache[a];
-                               if(path->steps > 0) {
-                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+                       glDisable(GL_COLOR_MATERIAL);
+                       glDisable(GL_LIGHTING);
+                       UI_ThemeColor(TH_WIRE);
+               }
 
-                                       if(ob_dt > OB_WIRE) {
-                                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
-                                               if(part->draw&PART_DRAW_MAT_COL)
-                                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
-                                       }
+               if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+                       totpart=0;
 
-                                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
-                               }
-                       }
-                       
-                       /* draw child particles */
-                       cache=psys->childcache;
-                       for(a=0; a<totchild; a++){
-                               path=cache[a];
+               /* draw actual/parent particles */
+               cache=psys->pathcache;
+               for(a=0, pa=psys->particles; a<totpart; a++, pa++){
+                       path=cache[a];
+                       if(path->steps > 0) {
                                glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
                                if(ob_dt > OB_WIRE) {
@@ -3996,86 +4007,104 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
                                glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
                        }
+               }
+               
+               /* draw child particles */
+               cache=psys->childcache;
+               for(a=0; a<totchild; a++){
+                       path=cache[a];
+                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
-
-                       /* restore & clean up */
                        if(ob_dt > OB_WIRE) {
+                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
                                if(part->draw&PART_DRAW_MAT_COL)
-                                       glDisable(GL_COLOR_ARRAY);
-                               glDisable(GL_COLOR_MATERIAL);
+                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
                        }
 
-                       if(cdata2)
-                               MEM_freeN(cdata2);
-                       cd2=cdata2=0;
+                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+               }
 
-                       glLineWidth(1.0f);
+
+               /* restore & clean up */
+               if(ob_dt > OB_WIRE) {
+                       if(part->draw&PART_DRAW_MAT_COL)
+                               glDisable(GL_COLOR_ARRAY);
+                       glDisable(GL_COLOR_MATERIAL);
                }
-               else if(draw_as!=PART_DRAW_CIRC){
-                       glDisableClientState(GL_COLOR_ARRAY);
 
-                       /* setup created data arrays */
-                       if(pdd->vdata){
-                               glEnableClientState(GL_VERTEX_ARRAY);
-                               glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
-                       }
+               if(cdata2)
+                       MEM_freeN(cdata2);
+               cd2=cdata2=0;
+
+               glLineWidth(1.0f);
+       }
+       else if(ELEM(draw_as, 0, PART_DRAW_CIRC)==0){
+               int point_size = 1;
+               glDisableClientState(GL_COLOR_ARRAY);
+
+               /* enable point data array */
+               if(pdd->vdata){
+                       glEnableClientState(GL_VERTEX_ARRAY);
+                       glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
+               }
+               else
+                       glDisableClientState(GL_VERTEX_ARRAY);
+
+               if(select) {
+                       UI_ThemeColor(TH_ACTIVE);
+                       
+                       if(part->draw_size)
+                               glPointSize(part->draw_size + 2);
                        else
-                               glDisableClientState(GL_VERTEX_ARRAY);
+                               glPointSize(4.0);
 
-                       /* billboards are drawn this way */
-                       if(pdd->ndata && ob_dt>OB_WIRE){
-                               glEnableClientState(GL_NORMAL_ARRAY);
-                               glNormalPointer(GL_FLOAT, 0, pdd->ndata);
-                               glEnable(GL_LIGHTING);
-                       }
-                       else{
-                               glDisableClientState(GL_NORMAL_ARRAY);
-                               glDisable(GL_LIGHTING);
-                       }
+                       glLineWidth(3.0);
 
-                       if(pdd->cdata){
-                               glEnableClientState(GL_COLOR_ARRAY);
-                               glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
-                       }
+                       draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
+               }
 
-                       /* draw created data arrays */
-                       switch(draw_as){
-                               case PART_DRAW_AXIS:
-                               case PART_DRAW_CROSS:
-                                       glDrawArrays(GL_LINES, 0, 6*totpoint);
-                                       break;
-                               case PART_DRAW_LINE:
-                                       glDrawArrays(GL_LINES, 0, 2*totpoint);
-                                       break;
-                               case PART_DRAW_BB:
-                                       if(ob_dt<=OB_WIRE)
-                                               glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
-
-                                       glDrawArrays(GL_QUADS, 0, 4*totpoint);
-                                       break;
-                               default:
-                                       glDrawArrays(GL_POINTS, 0, totpoint);
-                                       break;
-                       }
+               /* restore from select */
+               glColor3f(ma_r,ma_g,ma_b);
+               glPointSize(part->draw_size ? part->draw_size : 2.0);
+               glLineWidth(1.0);
+
+               /* enable other data arrays */
 
-                       pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
-                       pdd->totpoint = totpoint;
+               /* billboards are drawn this way */
+               if(pdd->ndata && ob_dt>OB_WIRE){
+                       glEnableClientState(GL_NORMAL_ARRAY);
+                       glNormalPointer(GL_FLOAT, 0, pdd->ndata);
+                       glEnable(GL_LIGHTING);
+               }
+               else{
+                       glDisableClientState(GL_NORMAL_ARRAY);
+                       glDisable(GL_LIGHTING);
                }
 
-               if(pdd->vedata){
-                       glDisableClientState(GL_COLOR_ARRAY);
-                       cpack(0xC0C0C0);
-                       
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                       glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
-                       
-                       glDrawArrays(GL_LINES, 0, 2*totve);
+               if(pdd->cdata){
+                       glEnableClientState(GL_COLOR_ARRAY);
+                       glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
                }
 
-               glPolygonMode(GL_FRONT, polygonmode[0]);
-               glPolygonMode(GL_BACK, polygonmode[1]);
+               draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
+
+               pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
+               pdd->totpoint = totpoint;
+       }
+
+       if(pdd && pdd->vedata){
+               glDisableClientState(GL_COLOR_ARRAY);
+               cpack(0xC0C0C0);
+               
+               glEnableClientState(GL_VERTEX_ARRAY);
+               glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
+               
+               glDrawArrays(GL_LINES, 0, 2*totve);
        }
 
+       glPolygonMode(GL_FRONT, polygonmode[0]);
+       glPolygonMode(GL_BACK, polygonmode[1]);
+
 /* 7. */
        
        glDisable(GL_LIGHTING);
@@ -4087,6 +4116,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        psys->flag &= ~PSYS_DRAWING;
 
+       /* draw data can't be saved for billboards as they must update to target changes */
+       if(draw_as == PART_DRAW_BB) {
+               psys_free_pdd(psys);
+               pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
+       }
+
        if(psys->lattice){
                end_latt_deform(psys->lattice);
                psys->lattice= NULL;
index e7e785e605b9bd61f6f0a8da9e7afdca8e43ac55..1376a08eb3e554d9c153968261c3009452d27890 100644 (file)
@@ -56,14 +56,14 @@ typedef enum PFieldType {
 } PFieldType;
        
 typedef struct PartDeflect {
+       int       flag;                 /* general settings flag                                                                                */
        short deflect;          /* Deflection flag - does mesh deflect particles                                */
        short forcefield;       /* Force field type, do the vertices attract / repel particles? */
-       short flag;                     /* general settings flag                                                                                */
        short falloff;          /* fall-off type                                                                                                */
        short shape;            /* point, plane or surface                                                                              */
        short tex_mode;         /* texture effector                                                                                             */
        short kink, kink_axis; /* for curve guide                                                                                       */
-       short zdir, rt;
+       short zdir;
        
        /* Main effector values */
        float f_strength;       /* The strength of the force (+ or - )                                  */
index 4c620ae527e4c643442db0d528215e6e52e91941..157767e1d1372a9895b30f7cd3b0c1a59e4ce207 100644 (file)
@@ -78,6 +78,13 @@ typedef struct ParticleTarget {
        float time, duration;
 } ParticleTarget;
 
+typedef struct ParticleDupliWeight {
+       struct ParticleDupliWeight *next, *prev;
+       struct Object *ob;
+       short count;
+       short flag, rt[2];
+} ParticleDupliWeight;
+
 typedef struct ParticleData {
        ParticleKey state;              /* current global coordinates */
 
@@ -148,6 +155,7 @@ typedef struct ParticleSettings {
 
        /* initial velocity factors */
        float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac;
+       float ob_vel[3], rt;
        float avefac, phasefac, randrotfac, randphasefac;
        /* physical properties */
        float mass, size, randsize, reactshape;
@@ -179,6 +187,7 @@ typedef struct ParticleSettings {
        int keyed_loops;
 
        struct Group *dup_group;
+       struct ListBase dupliweights;
        struct Group *eff_group;                // deprecated
        struct Object *dup_ob;
        struct Object *bb_ob;
@@ -324,12 +333,12 @@ typedef struct ParticleSystem{                            /* note, make sure all (runtime) are NULL's in
 
 /* part->draw */
 #define PART_DRAW_VEL          1
-//#define PART_DRAW_PATH_LEN   2
+#define PART_DRAW_GLOBAL_OB    2
 #define PART_DRAW_SIZE         4
 #define PART_DRAW_EMITTER      8       /* render emitter also */
 #define PART_DRAW_HEALTH       16
 #define PART_ABS_PATH_TIME  32
-//#define PART_DRAW_TRAIL              64      /* deprecated */
+#define PART_DRAW_COUNT_GR     64
 #define PART_DRAW_BB_LOCK      128
 #define PART_DRAW_PARENT       256
 #define PART_DRAW_NUM          512
@@ -444,6 +453,9 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PARS_ALIVE                     3
 #define PARS_DYING                     4
 
+/* ParticleDupliWeight->flag */
+#define PART_DUPLIW_CURRENT    1
+
 /* psys->vg */
 #define PSYS_TOT_VG                    12
 
index 022c04240af2d8de98a10469223c8c02ecb81649..404223ab590bb344a5d7cc4efb007b4412a31604 100644 (file)
@@ -45,6 +45,13 @@ EnumPropertyItem effector_shape_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+EnumPropertyItem curve_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
+       {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
 EnumPropertyItem empty_shape_items[] = {
        {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
        {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
@@ -59,6 +66,13 @@ EnumPropertyItem vortex_shape_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+EnumPropertyItem curve_vortex_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
+       {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve (New)", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
 EnumPropertyItem empty_vortex_shape_items[] = {
        {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
        {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
@@ -538,9 +552,11 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr,
                
                /* needed for doc generation */
                RNA_enum_items_add(&item, &totitem, effector_shape_items);
+               RNA_enum_items_add(&item, &totitem, curve_shape_items);
                RNA_enum_items_add(&item, &totitem, empty_shape_items);
                RNA_enum_items_add(&item, &totitem, vortex_shape_items);
-               RNA_enum_items_add(&item, &totitem, empty_shape_items);
+               RNA_enum_items_add(&item, &totitem, curve_vortex_shape_items);
+               RNA_enum_items_add(&item, &totitem, empty_vortex_shape_items);
                RNA_enum_item_end(&item, &totitem);
                
                *free= 1;
@@ -553,7 +569,13 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr,
        
        ob= (Object*)ptr->id.data;
        
-       if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
+       if(ob->type == OB_CURVE) {
+               if(ob->pd->forcefield == PFIELD_VORTEX)
+                       return curve_vortex_shape_items;
+
+               return curve_shape_items;
+       }
+       else if(ELEM3(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
                if(ob->pd->forcefield == PFIELD_VORTEX)
                        return vortex_shape_items;
 
@@ -783,11 +805,11 @@ static void rna_def_effector_weight(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "All", "All effector's weight.");
        RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
 
-       prop= RNA_def_property(srna, "spherical", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "force", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "weight[1]");
        RNA_def_property_range(prop, -200.0f, 200.0f);
        RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
-       RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight.");
+       RNA_def_property_ui_text(prop, "Force", "Force effector weight.");
        RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
 
        prop= RNA_def_property(srna, "vortex", PROP_FLOAT, PROP_NONE);
@@ -1113,6 +1135,11 @@ static void rna_def_field(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_DO_ROTATION);
        RNA_def_property_ui_text(prop, "Rotation", "Effect particles' dynamic rotation");
        RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+
+       prop= RNA_def_property(srna, "do_absorption", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY);
+       RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects");
+       RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
        
        /* Pointer */
        
index 453b5f9f91ab5d8dc439ea7ecf6229d7107ad3c8..2c81bda121f526a8c682b6ed8dec377b09b9a5ee 100644 (file)
@@ -105,6 +105,7 @@ EnumPropertyItem part_hair_ren_as_items[] = {
 #include "BKE_pointcache.h"
 
 #include "BLI_arithb.h"
+#include "BLI_listbase.h"
 
 /* property update functions */
 static void particle_recalc(bContext *C, PointerRNA *ptr, short flag)
@@ -433,6 +434,71 @@ static int rna_ParticleSystem_edited_get(PointerRNA *ptr)
        else
                return (psys->pointcache->edit && psys->pointcache->edit->edited);
 }
+static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
+{
+       ParticleSettings *part= (ParticleSettings*)ptr->id.data;
+       ParticleDupliWeight *dw = part->dupliweights.first;
+
+       for(; dw; dw=dw->next) {
+               if(dw->flag & PART_DUPLIW_CURRENT)
+                       return rna_pointer_inherit_refine(ptr, &RNA_ParticleDupliWeight, dw);
+       }
+       return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
+}
+static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max)
+{
+       ParticleSettings *part= (ParticleSettings*)ptr->id.data;
+       *min= 0;
+       *max= BLI_countlist(&part->dupliweights)-1;
+       *max= MAX2(0, *max);
+}
+
+static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
+{
+       ParticleSettings *part= (ParticleSettings*)ptr->id.data;
+       ParticleDupliWeight *dw = part->dupliweights.first;
+       int i=0;
+
+       for(; dw; dw=dw->next, i++)
+               if(dw->flag & PART_DUPLIW_CURRENT)
+                       return i;
+
+       return 0;
+}
+
+static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value)
+{
+       ParticleSettings *part= (ParticleSettings*)ptr->id.data;
+       ParticleDupliWeight *dw = part->dupliweights.first;
+       int i=0;
+
+       for(; dw; dw=dw->next, i++) {
+               if(i==value)
+                       dw->flag |= PART_DUPLIW_CURRENT;
+               else
+                       dw->flag &= ~PART_DUPLIW_CURRENT;
+       }
+}
+
+static int rna_ParticleDupliWeight_name_length(PointerRNA *ptr)
+{
+       ParticleDupliWeight *dw= ptr->data;
+
+       if(dw->ob)
+               return strlen(dw->ob->id.name+2) + 7;
+       else
+               return 9 + 7;
+}
+
+static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str)
+{
+       ParticleDupliWeight *dw= ptr->data;
+
+       if(dw->ob)
+               sprintf(str, "%s: %i", dw->ob->id.name+2, dw->count);
+       else
+               strcpy(str, "No object");
+}
 EnumPropertyItem from_items[] = {
        {PART_FROM_VERT, "VERT", 0, "Vertexes", ""},
        {PART_FROM_FACE, "FACE", 0, "Faces", ""},
@@ -726,6 +792,27 @@ static void rna_def_particle(BlenderRNA *brna)
 //     short rt2;
 }
 
+static void rna_def_particle_dupliweight(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "ParticleDupliWeight", NULL);
+       RNA_def_struct_ui_text(srna, "Particle Dupliobject Weight", "Weight of a particle dupliobject in a group.");
+       RNA_def_struct_sdna(srna, "ParticleDupliWeight");
+
+       prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_funcs(prop, "rna_ParticleDupliWeight_name_get", "rna_ParticleDupliWeight_name_length", NULL);
+       RNA_def_property_ui_text(prop, "Name", "Particle dupliobject name.");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_struct_name_property(srna, prop);
+
+       prop= RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_range(prop, 0, INT_MAX);
+       RNA_def_property_ui_text(prop, "Count", "The number of times this object is repeated with respect to other objects.");
+       RNA_def_property_update(prop, 0, "rna_Particle_redo");
+}
+
 static void rna_def_particle_settings(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -1069,6 +1156,16 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Pick Random", "Pick objects from group randomly");
        RNA_def_property_update(prop, 0, "rna_Particle_redo");
 
+       prop= RNA_def_property(srna, "use_group_count", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_COUNT_GR);
+       RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same group");
+       RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
+       prop= RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB);
+       RNA_def_property_ui_text(prop, "Use Global", "Use object's global coordinates for duplication.");
+       RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
        prop= RNA_def_property(srna, "render_adaptive", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
        RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path");
@@ -1374,6 +1471,13 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Reactor", "Let the vector away from the target particles location give the particle a starting speed.");
        RNA_def_property_update(prop, 0, "rna_Particle_reset");
 
+       prop= RNA_def_property(srna, "object_aligned_factor", PROP_FLOAT, PROP_VELOCITY);
+       RNA_def_property_float_sdna(prop, NULL, "ob_vel");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_text(prop, "Object Aligned", "Let the emitter object orientation give the particle a starting speed");
+       RNA_def_property_update(prop, 0, "rna_Particle_reset");
+
        prop= RNA_def_property(srna, "angular_velocity_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "avefac");
        RNA_def_property_range(prop, -200.0f, 200.0f);
@@ -1426,19 +1530,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
 
        /* global physical properties */
-       prop= RNA_def_property(srna, "acceleration", PROP_FLOAT, PROP_ACCELERATION);
-       RNA_def_property_float_sdna(prop, NULL, "acc");
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_range(prop, -200.0f, 200.0f);
-       RNA_def_property_ui_text(prop, "Acceleration", "Constant acceleration");
-       RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
-       prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
-       RNA_def_property_float_sdna(prop, NULL, "acc[2]");
-       RNA_def_property_range(prop, -200.0f, 200.0f);
-       RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in global Z axis direction");
-       RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
        prop= RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "dragfac");
        RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1665,6 +1756,19 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Dupli Group", "Show Objects in this Group in place of particles");
        RNA_def_property_update(prop, 0, "rna_Particle_redo");
 
+       prop= RNA_def_property(srna, "dupliweights", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_struct_type(prop, "ParticleDupliWeight");
+       RNA_def_property_ui_text(prop, "Dupli Group Weights", "Weights for all of the objects in the dupli group.");
+
+       prop= RNA_def_property(srna, "active_dupliweight", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "ParticleDupliWeight");
+       RNA_def_property_pointer_funcs(prop, "rna_ParticleDupliWeight_active_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Active Dupli Object", "");
+
+       prop= RNA_def_property(srna, "active_dupliweight_index", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_funcs(prop, "rna_ParticleDupliWeight_active_index_get", "rna_ParticleDupliWeight_active_index_set", "rna_ParticleDupliWeight_active_index_range");
+       RNA_def_property_ui_text(prop, "Active Dupli Object Index", "");
+
        prop= RNA_def_property(srna, "dupli_object", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "dup_ob");
        RNA_def_property_struct_type(prop, "Object");
@@ -2024,6 +2128,7 @@ void RNA_def_particle(BlenderRNA *brna)
 
        rna_def_child_particle(brna);
        rna_def_particle(brna);
+       rna_def_particle_dupliweight(brna);
        rna_def_particle_system(brna);
        rna_def_particle_settings(brna);
 }