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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/ui/buttons_particle.py106
-rw-r--r--release/scripts/ui/buttons_physics_common.py5
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h4
-rw-r--r--source/blender/blenkernel/BKE_effect.h1
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/intern/anim.c43
-rw-r--r--source/blender/blenkernel/intern/boids.c5
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c88
-rw-r--r--source/blender/blenkernel/intern/effect.c21
-rw-r--r--source/blender/blenkernel/intern/modifier.c8
-rw-r--r--source/blender/blenkernel/intern/particle.c81
-rw-r--r--source/blender/blenkernel/intern/particle_system.c28
-rw-r--r--source/blender/blenkernel/intern/pointcache.c24
-rw-r--r--source/blender/blenloader/intern/readfile.c7
-rw-r--r--source/blender/blenloader/intern/writefile.c5
-rw-r--r--source/blender/editors/physics/particle_object.c76
-rw-r--r--source/blender/editors/physics/physics_intern.h3
-rw-r--r--source/blender/editors/physics/physics_ops.c3
-rw-r--r--source/blender/editors/space_view3d/drawobject.c499
-rw-r--r--source/blender/makesdna/DNA_object_force.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c35
-rw-r--r--source/blender/makesrna/intern/rna_particle.c131
23 files changed, 873 insertions, 322 deletions
diff --git a/release/scripts/ui/buttons_particle.py b/release/scripts/ui/buttons_particle.py
index 1a800fc4dfd..81ddab40ec9 100644
--- a/release/scripts/ui/buttons_particle.py
+++ b/release/scripts/ui/buttons_particle.py
@@ -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)
diff --git a/release/scripts/ui/buttons_physics_common.py b/release/scripts/ui/buttons_physics_common.py
index b65d092fcfa..17ac1b2bbaa 100644
--- a/release/scripts/ui/buttons_physics_common.py
+++ b/release/scripts/ui/buttons_physics_common.py
@@ -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")
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 66c8d99959a..e2911a30b25 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -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;
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 83ec7c13946..9a0a724ab9a 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -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
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index e0259ff10dd..e9285782a1e 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index bd779935d55..5cd901066f8 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -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
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 76824d3a34a..712fb13cfc0 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index d9e005811d0..f2526231d50 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -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)
{
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 7cc65de827a..9b648e2c05c 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -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:
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 3b47c2f1830..55fb9f45bb3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -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);
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index f4f5a1364a3..011d5c3f134 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index d757372f17b..45050127582 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index bffe4566f74..fa0d5cba604 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -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)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a3a56e9a075..989e2b3fa9e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 1f46446dc2a..c92c0909d3b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index cef630b6711..1dc08a162b7 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -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)
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 956f26c478d..3847ec8032a 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -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);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index a62d3d8fd78..ddc5fb9c9b6 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -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)
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 0f2a57d881c..0659b5cfd11 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -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;
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index e7e785e605b..1376a08eb3e 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -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 - ) */
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 4c620ae527e..157767e1d13 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -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
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 022c04240af..404223ab590 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -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 */
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 453b5f9f91a..2c81bda121f 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -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);
}