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:
authorLukas Tönne <lukas.toenne@gmail.com>2016-12-28 19:30:58 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-12-28 19:30:58 +0300
commit6ecab6dd8e48d564a2b43e0e81e79d079e8b4c77 (patch)
tree618e2d24eb34a05a81f726dd52eb2b7468e9296d /source/blender/editors/space_view3d
parent605263177b8eea24c1449e4dbf0138175ec3dddf (diff)
Revert particle system and point cache removal in blender2.8 branch.
This reverts commit 5aa19be91263a249ffae75573e3b32f24269d890 and b4a721af694817fa921b119df83d33ede7d7fed0. Due to postponement of particle system rewrite it was decided to put particle code back into the 2.8 branch for the time being.
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/drawobject.c1206
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c12
8 files changed, 1222 insertions, 12 deletions
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 8b2738914d9..46d682233ed 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -37,7 +37,6 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-#include "DNA_object_force.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -72,6 +71,8 @@
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
#include "BKE_unit.h"
@@ -94,6 +95,7 @@
#include "GPU_matrix.h"
#include "ED_mesh.h"
+#include "ED_particle.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_types.h"
@@ -4737,7 +4739,12 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
* with the background. */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f);
+ }
+ else {
+ glColor3ubv(ob_wire_col);
+ }
}
/* If drawing wire and drawtype is not OB_WIRE then we are
@@ -5784,6 +5791,1113 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
}
/* *********** 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], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd)
+{
+ float vec[3], vec2[3];
+ float *vd = NULL;
+ float *cd = NULL;
+ float ma_col[3] = {0.0f, 0.0f, 0.0f};
+
+ /* null only for PART_DRAW_CIRC */
+ if (pdd) {
+ vd = pdd->vd;
+ cd = pdd->cd;
+
+ if (pdd->ma_col) {
+ copy_v3_v3(ma_col, pdd->ma_col);
+ }
+ }
+
+ switch (draw_as) {
+ case PART_DRAW_DOT:
+ {
+ if (vd) {
+ copy_v3_v3(vd, state->co); pdd->vd += 3;
+ }
+ if (cd) {
+ copy_v3_v3(cd, pdd->ma_col);
+ pdd->cd += 3;
+ }
+ break;
+ }
+ case PART_DRAW_CROSS:
+ case PART_DRAW_AXIS:
+ {
+ vec[0] = 2.0f * pixsize;
+ vec[1] = vec[2] = 0.0;
+ mul_qt_v3(state->rot, vec);
+ if (draw_as == PART_DRAW_AXIS) {
+ if (cd) {
+ cd[1] = cd[2] = cd[4] = cd[5] = 0.0;
+ cd[0] = cd[3] = 1.0;
+ cd[6] = cd[8] = cd[9] = cd[11] = 0.0;
+ cd[7] = cd[10] = 1.0;
+ cd[13] = cd[12] = cd[15] = cd[16] = 0.0;
+ cd[14] = cd[17] = 1.0;
+ pdd->cd += 18;
+ }
+
+ copy_v3_v3(vec2, state->co);
+ }
+ else {
+ if (cd) {
+ cd[0] = cd[3] = cd[6] = cd[9] = cd[12] = cd[15] = ma_col[0];
+ cd[1] = cd[4] = cd[7] = cd[10] = cd[13] = cd[16] = ma_col[1];
+ cd[2] = cd[5] = cd[8] = cd[11] = cd[14] = cd[17] = ma_col[2];
+ pdd->cd += 18;
+ }
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
+
+ add_v3_v3(vec, state->co);
+ copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
+ copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
+
+ vec[1] = 2.0f * pixsize;
+ vec[0] = vec[2] = 0.0;
+ mul_qt_v3(state->rot, vec);
+ if (draw_as == PART_DRAW_AXIS) {
+ copy_v3_v3(vec2, state->co);
+ }
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
+
+ add_v3_v3(vec, state->co);
+ copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
+ copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
+
+ vec[2] = 2.0f * pixsize;
+ vec[0] = vec[1] = 0.0f;
+ mul_qt_v3(state->rot, vec);
+ if (draw_as == PART_DRAW_AXIS) {
+ copy_v3_v3(vec2, state->co);
+ }
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
+
+ add_v3_v3(vec, state->co);
+
+ copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
+ copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
+ break;
+ }
+ case PART_DRAW_LINE:
+ {
+ copy_v3_v3(vec, state->vel);
+ normalize_v3(vec);
+ if (draw & PART_DRAW_VEL_LENGTH)
+ mul_v3_fl(vec, len_v3(state->vel));
+ madd_v3_v3v3fl(pdd->vd, state->co, vec, -draw_line[0]); pdd->vd += 3;
+ madd_v3_v3v3fl(pdd->vd, state->co, vec, draw_line[1]); pdd->vd += 3;
+ if (cd) {
+ cd[0] = cd[3] = ma_col[0];
+ cd[1] = cd[4] = ma_col[1];
+ cd[2] = cd[5] = ma_col[2];
+ pdd->cd += 6;
+ }
+ break;
+ }
+ case PART_DRAW_CIRC:
+ {
+ drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
+ break;
+ }
+ case PART_DRAW_BB:
+ {
+ float xvec[3], yvec[3], zvec[3], bb_center[3];
+ if (cd) {
+ cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0];
+ cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1];
+ cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2];
+ pdd->cd += 12;
+ }
+
+ copy_v3_v3(bb->vec, state->co);
+ copy_v3_v3(bb->vel, state->vel);
+
+ psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
+
+ add_v3_v3v3(pdd->vd, bb_center, xvec);
+ add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
+
+ sub_v3_v3v3(pdd->vd, bb_center, xvec);
+ add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
+
+ sub_v3_v3v3(pdd->vd, bb_center, xvec);
+ sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+
+ add_v3_v3v3(pdd->vd, bb_center, xvec);
+ sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+
+ copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
+ copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
+ copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
+ copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
+ break;
+ }
+ }
+}
+static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
+ ParticleKey *state, int draw_as,
+ float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd,
+ const float ct, const float pa_size, const float r_tilt, const float pixsize_scale)
+{
+ ParticleSettings *part = psys->part;
+ float pixsize;
+
+ if (psys->parent)
+ mul_m4_v3(psys->parent->obmat, state->co);
+
+ /* create actual particle data */
+ if (draw_as == PART_DRAW_BB) {
+ bb->offset[0] = part->bb_offset[0];
+ bb->offset[1] = part->bb_offset[1];
+ bb->size[0] = part->bb_size[0] * pa_size;
+ if (part->bb_align == PART_BB_VEL) {
+ float pa_vel = len_v3(state->vel);
+ float head = part->bb_vel_head * pa_vel;
+ float tail = part->bb_vel_tail * pa_vel;
+ bb->size[1] = part->bb_size[1] * pa_size + head + tail;
+ /* use offset to adjust the particle center. this is relative to size, so need to divide! */
+ if (bb->size[1] > 0.0f)
+ bb->offset[1] += (head - tail) / bb->size[1];
+ }
+ else {
+ bb->size[1] = part->bb_size[1] * pa_size;
+ }
+ bb->tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+ bb->time = ct;
+ }
+
+ pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale;
+
+ draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
+}
+/* unified drawing of all new particle systems draw types except dupli ob & group
+ * mostly tries to use vertex arrays for speed
+ *
+ * 1. check that everything is ok & updated
+ * 2. start initializing things
+ * 3. initialize according to draw type
+ * 4. allocate drawing data arrays
+ * 5. start filling the arrays
+ * 6. draw the arrays
+ * 7. clean up
+ */
+static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ Base *base, ParticleSystem *psys,
+ const char ob_dt, const short dflag)
+{
+ Object *ob = base->object;
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleSettings *part = psys->part;
+ ParticleData *pars = psys->particles;
+ ParticleData *pa;
+ ParticleKey state, *states = NULL;
+ ParticleBillboardData bb;
+ ParticleSimulationData sim = {NULL};
+ ParticleDrawData *pdd = psys->pdd;
+ Material *ma;
+ float vel[3], imat[4][4];
+ float timestep, pixsize_scale = 1.0f, pa_size, r_tilt, r_length;
+ float pa_time, pa_birthtime, pa_dietime, pa_health, intensity;
+ float cfra;
+ float ma_col[3] = {0.0f, 0.0f, 0.0f};
+ int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0;
+ bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false;
+ GLint polygonmode[2];
+ char numstr[32];
+ unsigned char tcol[4] = {0, 0, 0, 255};
+
+/* 1. */
+ if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering))
+ return;
+
+ if (pars == NULL) return;
+
+ /* don't draw normal paths in edit mode */
+ if (psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART) == 0)
+ 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;
+
+ /* prepare curvemapping tables */
+ if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
+ curvemapping_changed_all(psys->part->clumpcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
+ curvemapping_changed_all(psys->part->roughcurve);
+
+/* 2. */
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
+
+ if (part->phystype == PART_PHYS_KEYED) {
+ if (psys->flag & PSYS_KEYED) {
+ psys_count_keyed_targets(&sim);
+ if (psys->totkeyed == 0)
+ return;
+ }
+ }
+
+ if (select) {
+ select = false;
+ if (psys_get_current(ob) == psys)
+ select = true;
+ }
+
+ psys->flag |= PSYS_DRAWING;
+
+ if (part->type == PART_HAIR && !psys->childcache)
+ totchild = 0;
+ else
+ totchild = psys->totchild * part->disp / 100;
+
+ ma = give_current_material(ob, part->omat);
+
+ if (v3d->zbuf) glDepthMask(1);
+
+ if ((ma) && (part->draw_col == PART_DRAW_COL_MAT)) {
+ rgb_float_to_uchar(tcol, &(ma->r));
+ copy_v3_v3(ma_col, &ma->r);
+ }
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glColor3ubv(tcol);
+ }
+
+ timestep = psys_get_timestep(&sim);
+
+ if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ float mat[4][4];
+ mul_m4_m4m4(mat, ob->obmat, psys->imat);
+ glMultMatrixf(mat);
+ }
+
+ /* needed for text display */
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ totpart = psys->totpart;
+
+ cfra = BKE_scene_frame_get(scene);
+
+ if (draw_as == PART_DRAW_PATH && psys->pathcache == NULL && psys->childcache == NULL)
+ draw_as = PART_DRAW_DOT;
+
+/* 3. */
+ glLineWidth(1.0f);
+
+ switch (draw_as) {
+ case PART_DRAW_DOT:
+ if (part->draw_size)
+ glPointSize(part->draw_size);
+ else
+ glPointSize(2.0); /* default dot size */
+ break;
+ case PART_DRAW_CIRC:
+ /* calculate view aligned matrix: */
+ copy_m4_m4(imat, rv3d->viewinv);
+ normalize_v3(imat[0]);
+ normalize_v3(imat[1]);
+ /* fall-through */
+ case PART_DRAW_CROSS:
+ case PART_DRAW_AXIS:
+ /* lets calculate the scale: */
+
+ if (part->draw_size == 0.0)
+ pixsize_scale = 2.0f;
+ else
+ pixsize_scale = part->draw_size;
+
+ if (draw_as == PART_DRAW_AXIS)
+ create_cdata = 1;
+ break;
+ case PART_DRAW_OB:
+ if (part->dup_ob == NULL)
+ draw_as = PART_DRAW_DOT;
+ else
+ draw_as = 0;
+ break;
+ case PART_DRAW_GR:
+ if (part->dup_group == NULL)
+ draw_as = PART_DRAW_DOT;
+ else
+ draw_as = 0;
+ break;
+ case PART_DRAW_BB:
+ if (v3d->camera == NULL && part->bb_ob == NULL) {
+ printf("Billboards need an active camera or a target object!\n");
+
+ draw_as = part->draw_as = PART_DRAW_DOT;
+
+ if (part->draw_size)
+ glPointSize(part->draw_size);
+ else
+ glPointSize(2.0); /* default dot size */
+ }
+ else if (part->bb_ob)
+ bb.ob = part->bb_ob;
+ else
+ bb.ob = v3d->camera;
+
+ bb.align = part->bb_align;
+ bb.anim = part->bb_anim;
+ bb.lock = part->draw & PART_DRAW_BB_LOCK;
+ break;
+ case PART_DRAW_PATH:
+ break;
+ case PART_DRAW_LINE:
+ need_v = 1;
+ break;
+ }
+ if (part->draw & PART_DRAW_SIZE && part->draw_as != PART_DRAW_CIRC) {
+ copy_m4_m4(imat, rv3d->viewinv);
+ normalize_v3(imat[0]);
+ normalize_v3(imat[1]);
+ }
+
+ if (ELEM(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
+ (part->draw_col > PART_DRAW_COL_MAT))
+ {
+ create_cdata = 1;
+ }
+
+ if (!create_cdata && pdd && pdd->cdata) {
+ MEM_freeN(pdd->cdata);
+ pdd->cdata = pdd->cd = NULL;
+ }
+
+/* 4. */
+ 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), "ParticleDrawData");
+
+ if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
+ tot_vec_size *= part->trail_count;
+ 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 (!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_ndata");
+
+ if (part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
+ if (!pdd->vedata)
+ pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
+
+ need_v = 1;
+ }
+ else if (pdd->vedata) {
+ /* velocity data not needed, so free it */
+ MEM_freeN(pdd->vedata);
+ pdd->vedata = NULL;
+ }
+
+ pdd->vd = pdd->vdata;
+ pdd->ved = pdd->vedata;
+ pdd->cd = pdd->cdata;
+ pdd->nd = pdd->ndata;
+ pdd->tot_vec_size = tot_vec_size;
+ }
+ else if (psys->pdd) {
+ psys_free_pdd(psys);
+ MEM_freeN(psys->pdd);
+ pdd = psys->pdd = NULL;
+ }
+
+ if (pdd) {
+ pdd->ma_col = ma_col;
+ }
+
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ /* circles don't use drawdata, so have to add a special case here */
+ if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
+ /* 5. */
+ if (pdd && (pdd->flag & PARTICLE_DRAW_DATA_UPDATED) &&
+ (pdd->vedata || part->draw & (PART_DRAW_SIZE | PART_DRAW_NUM | PART_DRAW_HEALTH)) == 0)
+ {
+ totpoint = pdd->totpoint; /* draw data is up to date */
+ }
+ else {
+ for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) {
+ /* setup per particle individual stuff */
+ if (a < totpart) {
+ if (totchild && (part->draw & PART_DRAW_PARENT) == 0) continue;
+ if (pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
+
+ pa_time = (cfra - pa->time) / pa->lifetime;
+ pa_birthtime = pa->time;
+ pa_dietime = pa->dietime;
+ pa_size = pa->size;
+ if (part->phystype == PART_PHYS_BOIDS)
+ pa_health = pa->boid->data.health;
+ else
+ pa_health = -1.0;
+
+ r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
+ r_length = psys_frand(psys, a + 22);
+
+ if (part->draw_col > PART_DRAW_COL_MAT) {
+ switch (part->draw_col) {
+ case PART_DRAW_COL_VEL:
+ intensity = len_v3(pa->state.vel) / part->color_vec_max;
+ break;
+ case PART_DRAW_COL_ACC:
+ intensity = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * part->color_vec_max);
+ break;
+ default:
+ intensity = 1.0f; /* should never happen */
+ BLI_assert(0);
+ break;
+ }
+ CLAMP(intensity, 0.0f, 1.0f);
+ weight_to_rgb(ma_col, intensity);
+ }
+ }
+ else {
+ ChildParticle *cpa = &psys->child[a - totpart];
+
+ pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
+ pa_size = psys_get_child_size(psys, cpa, cfra, NULL);
+
+ pa_health = -1.0;
+
+ r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
+ r_length = psys_frand(psys, a + 22);
+ }
+
+ drawn = 0;
+ if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
+ float length = part->path_end * (1.0f - part->randlength * r_length);
+ int trail_count = part->trail_count * (1.0f - 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);
+
+ draw_particle_data(psys, rv3d,
+ &state, draw_as, imat, &bb, psys->pdd,
+ ct, pa_size, r_tilt, pixsize_scale);
+
+ totpoint++;
+ drawn = 1;
+ }
+ }
+ else {
+ state.time = cfra;
+ if (psys_get_particle_state(&sim, a, &state, 0)) {
+
+ draw_particle_data(psys, rv3d,
+ &state, draw_as, imat, &bb, psys->pdd,
+ pa_time, pa_size, r_tilt, pixsize_scale);
+
+ totpoint++;
+ drawn = 1;
+ }
+ }
+
+ if (drawn) {
+ /* additional things to draw for each particle
+ * (velocity, size and number) */
+ if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) {
+ copy_v3_v3(pdd->ved, state.co);
+ pdd->ved += 3;
+ mul_v3_v3fl(vel, state.vel, timestep);
+ add_v3_v3v3(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_NUM || part->draw & PART_DRAW_HEALTH) &&
+ (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0)
+ {
+ size_t numstr_len;
+ float vec_txt[3];
+ char *val_pos = numstr;
+ numstr[0] = '\0';
+
+ if (part->draw & PART_DRAW_NUM) {
+ if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
+ }
+ else {
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a);
+ }
+ }
+ else {
+ if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health);
+ }
+ }
+
+ if (numstr[0]) {
+ /* in path drawing state.co is the end point
+ * use worldspace because object matrix is already applied */
+ mul_v3_m4v3(vec_txt, ob->imat, state.co);
+ view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
+ 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
+ }
+ }
+ }
+ }
+ }
+ }
+/* 6. */
+
+ glGetIntegerv(GL_POLYGON_MODE, polygonmode);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ if (draw_as == PART_DRAW_PATH) {
+ ParticleCacheKey **cache, *path;
+ float *cdata2 = NULL;
+
+ /* setup gl flags */
+ if (1) { //ob_dt > OB_WIRE) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ // XXX test
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
+ }
+
+ if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
+ totpart = 0;
+ else if (psys->pathcache == NULL)
+ totpart = 0;
+
+ /* draw actual/parent particles */
+ cache = psys->pathcache;
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ path = cache[a];
+ if (path->segments > 0) {
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+ if (1) { //ob_dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (part->draw_col == PART_DRAW_COL_MAT) {
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+ }
+ }
+
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ }
+ }
+
+ if (part->type == PART_HAIR) {
+ if (part->draw & PART_DRAW_GUIDE_HAIRS) {
+ DerivedMesh *hair_dm = psys->hair_out_dm;
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ if (pa->totkey > 1) {
+ HairKey *hkey = pa->hair;
+
+ glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
+
+#if 0 /* XXX use proper theme color here */
+ UI_ThemeColor(TH_NORMAL);
+#else
+ glColor3f(0.58f, 0.67f, 1.0f);
+#endif
+
+ glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
+ }
+ }
+
+ if (hair_dm) {
+ MVert *mvert = hair_dm->getVertArray(hair_dm);
+ int i;
+
+ glColor3f(0.9f, 0.4f, 0.4f);
+
+ glBegin(GL_LINES);
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ for (i = 1; i < pa->totkey; ++i) {
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
+ copy_v3_v3(v2, mvert[pa->hair_index + i].co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ }
+ }
+ glEnd();
+ }
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ if (part->draw & PART_DRAW_HAIR_GRID) {
+ ClothModifierData *clmd = psys->clmd;
+ if (clmd) {
+ float *gmin = clmd->hair_grid_min;
+ float *gmax = clmd->hair_grid_max;
+ int *res = clmd->hair_grid_res;
+ int i;
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ if (select)
+ UI_ThemeColor(TH_ACTIVE);
+ else
+ UI_ThemeColor(TH_WIRE);
+ glBegin(GL_LINES);
+ glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]);
+ glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]);
+ glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]);
+ glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]);
+
+ glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
+ glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
+ glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
+ glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
+
+ glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
+ glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
+ glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
+ glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
+ glEnd();
+
+ if (select)
+ UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
+ else
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
+ glEnable(GL_BLEND);
+ glBegin(GL_LINES);
+ for (i = 1; i < res[0] - 1; ++i) {
+ float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
+ glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]);
+ glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]);
+ glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]);
+ glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]);
+ }
+ for (i = 1; i < res[1] - 1; ++i) {
+ float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
+ glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]);
+ glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]);
+ glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]);
+ glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]);
+ }
+ for (i = 1; i < res[2] - 1; ++i) {
+ float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
+ glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f);
+ glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f);
+ glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f);
+ glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f);
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ }
+ }
+
+ /* draw child particles */
+ cache = psys->childcache;
+ for (a = 0; a < totchild; a++) {
+ path = cache[a];
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+ if (1) { //ob_dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (part->draw_col == PART_DRAW_COL_MAT) {
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+ }
+ }
+
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ }
+
+ /* restore & clean up */
+ if (1) { //ob_dt > OB_WIRE) {
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glDisableClientState(GL_COLOR_ARRAY);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ }
+
+ if (cdata2) {
+ MEM_freeN(cdata2);
+ cdata2 = NULL;
+ }
+
+ if ((part->draw & PART_DRAW_NUM) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ cache = psys->pathcache;
+
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ float vec_txt[3];
+ size_t numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a);
+ /* use worldspace because object matrix is already applied */
+ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
+ view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
+ 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
+ }
+ }
+ }
+ else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) {
+ 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 ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (select) {
+ UI_ThemeColor(TH_ACTIVE);
+
+ if (part->draw_size)
+ glPointSize(part->draw_size + 2);
+ else
+ glPointSize(4.0);
+
+ glLineWidth(3.0);
+
+ draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
+ }
+
+ /* restore from select */
+ glColor3fv(ma_col);
+ }
+
+ glPointSize(part->draw_size ? part->draw_size : 2.0);
+ glLineWidth(1.0);
+
+ /* enable other data arrays */
+
+ /* billboards are drawn this way */
+ if (pdd->ndata && ob_dt > OB_WIRE) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, 0, pdd->ndata);
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
+ }
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (pdd->cdata) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
+ }
+ }
+
+ draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
+
+ pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
+ pdd->totpoint = totpoint;
+ }
+
+ if (pdd && pdd->vedata) {
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glDisableClientState(GL_COLOR_ARRAY);
+ cpack(0xC0C0C0);
+ }
+
+ glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
+
+ glDrawArrays(GL_LINES, 0, 2 * totve);
+ }
+
+ glPolygonMode(GL_FRONT, polygonmode[0]);
+ glPolygonMode(GL_BACK, polygonmode[1]);
+
+/* 7. */
+
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ if (states)
+ MEM_freeN(states);
+
+ 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_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ if (pdd) {
+ /* drop references to stack memory */
+ pdd->ma_col = NULL;
+ }
+
+ if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ glLoadMatrixf(rv3d->viewmat);
+ }
+}
+
+static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit)
+{
+ if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
+ PE_update_object(scene, ob, 0);
+
+ /* create path and child path cache if it doesn't exist already */
+ if (edit->pathcache == NULL)
+ psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+}
+
+static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
+{
+ ParticleCacheKey **cache, *path, *pkey;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ ParticleEditSettings *pset = PE_settings(scene);
+ int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
+ int totkeys = 1;
+ float sel_col[3];
+ float nosel_col[3];
+ float *pathcol = NULL, *pcol;
+
+ if (edit->pathcache == NULL)
+ return;
+
+ PE_hide_keys_time(scene, edit, CFRA);
+
+ /* opengl setup */
+ if ((v3d->flag & V3D_ZBUF_SELECT) == 0)
+ glDisable(GL_DEPTH_TEST);
+
+ /* get selection theme colors */
+ UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
+ UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
+
+ /* draw paths */
+ totkeys = (*edit->pathcache)->segments + 1;
+
+ glEnable(GL_BLEND);
+ pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ if (pset->brushtype == PE_BRUSH_WEIGHT)
+ glLineWidth(2.0f);
+
+ cache = edit->pathcache;
+ for (i = 0, point = edit->points; i < totpoint; i++, point++) {
+ path = cache[i];
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+ if (point->flag & PEP_HIDE) {
+ for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
+ copy_v3_v3(pcol, path->col);
+ pcol[3] = 0.25f;
+ }
+
+ glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ }
+ else if (timed) {
+ for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
+ copy_v3_v3(pcol, pkey->col);
+ pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
+ }
+
+ glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ }
+ else
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ }
+
+ if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
+
+
+ /* draw edit vertices */
+ if (pset->selectmode != SCE_SELECT_PATH) {
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ if (pset->selectmode == SCE_SELECT_POINT) {
+ float *pd = NULL, *pdata = NULL;
+ float *cd = NULL, *cdata = NULL;
+ int totkeys_visible = 0;
+
+ for (i = 0, point = edit->points; i < totpoint; i++, point++)
+ if (!(point->flag & PEP_HIDE))
+ totkeys_visible += point->totkey;
+
+ if (totkeys_visible) {
+ if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
+ pd = pdata = MEM_callocN(totkeys_visible * 3 * sizeof(float), "particle edit point data");
+ cd = cdata = MEM_callocN(totkeys_visible * (timed ? 4 : 3) * sizeof(float), "particle edit color data");
+ }
+
+ for (i = 0, point = edit->points; i < totpoint; i++, point++) {
+ if (point->flag & PEP_HIDE)
+ continue;
+
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ if (pd) {
+ copy_v3_v3(pd, key->co);
+ pd += 3;
+ }
+
+ if (key->flag & PEK_SELECT) {
+ copy_v3_v3(cd, sel_col);
+ }
+ else {
+ copy_v3_v3(cd, nosel_col);
+ }
+
+ if (timed)
+ *(cd + 3) = 1.0f - fabsf((float)CFRA - *key->time) / (float)pset->fade_frames;
+
+ cd += (timed ? 4 : 3);
+ }
+ }
+ cd = cdata;
+ pd = pdata;
+ for (i = 0, point = edit->points; i < totpoint; i++, point++) {
+ if (point->flag & PEP_HIDE || point->totkey == 0)
+ continue;
+
+ if (point->keys->flag & PEK_USE_WCO)
+ glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
+ else
+ glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd);
+
+ glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd);
+
+ glDrawArrays(GL_POINTS, 0, point->totkey);
+
+ pd += pd ? 3 * point->totkey : 0;
+ cd += (timed ? 4 : 3) * point->totkey;
+ }
+ if (pdata) { MEM_freeN(pdata); pd = pdata = NULL; }
+ if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; }
+ }
+ else if (pset->selectmode == SCE_SELECT_END) {
+ glBegin(GL_POINTS);
+ for (i = 0, point = edit->points; i < totpoint; i++, point++) {
+ if ((point->flag & PEP_HIDE) == 0 && point->totkey) {
+ key = point->keys + point->totkey - 1;
+ glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col);
+ /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
+ glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
+ }
+ }
+ glEnd();
+ }
+ }
+
+ glDisable(GL_BLEND);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+}
static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size)
{
@@ -7459,12 +8573,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
Object *ob = base->object;
Curve *cu;
RegionView3D *rv3d = ar->regiondata;
+ unsigned int col = 0;
unsigned char _ob_wire_col[4]; /* dont initialize this */
const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */
bool zbufoff = false, is_paint = false, empty_object = false;
const bool is_obact = (ob == OBACT);
const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
const bool is_picking = (G.f & G_PICKSEL) != 0;
+ const bool has_particles = (ob->particlesystem.first != NULL);
+ bool skip_object = false; /* Draw particles but not their emitter object. */
SmokeModifierData *smd = NULL;
if (ob != scene->obedit) {
@@ -7475,11 +8592,31 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ob->restrictflag & OB_RESTRICT_RENDER)
return;
- if (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES))
+ if (!has_particles && (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES)))
return;
}
}
+ if (has_particles) {
+ /* XXX particles are not safe for simultaneous threaded render */
+ if (G.is_rendering) {
+ return;
+ }
+
+ if (ob->mode == OB_MODE_OBJECT) {
+ ParticleSystem *psys;
+
+ skip_object = render_override;
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ /* Once we have found a psys which renders its emitter object, we are done. */
+ if (psys->part->draw & PART_DRAW_EMITTER) {
+ skip_object = false;
+ break;
+ }
+ }
+ }
+ }
+
if (((base->flag & OB_FROMDUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Smoke)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)))
@@ -7505,8 +8642,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* xray delay? */
if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- /* sync with master */
- {
+ /* don't do xray in particle mode, need the z-buffer */
+ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
/* xray and transp are set when it is drawing the 2nd/3rd pass */
if (!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) {
ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
@@ -7608,8 +8745,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- /* sync with master */
- {
+ if (!skip_object) {
/* draw outline for selected objects, mesh does itself */
if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) {
if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) {
@@ -7758,6 +8894,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (!render_override) {
drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col);
}
+ break;
}
/* TODO Viewport: some elements are being drawn for object selection only */
@@ -7787,10 +8924,63 @@ afterdraw:
}
}
+ /* code for new particle system */
+ if ((ob->particlesystem.first) &&
+ (ob != scene->obedit))
+ {
+ ParticleSystem *psys;
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ /* for visibility, also while wpaint */
+ if (col || (ob->flag & SELECT)) {
+ cpack(0xFFFFFF);
+ }
+ }
+ //glDepthMask(GL_FALSE);
+
+ glLoadMatrixf(rv3d->viewmat);
+
+ view3d_cached_text_draw_begin();
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ /* run this so that possible child particles get cached */
+ if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
+ PTCacheEdit *edit = PE_create_current(scene, ob);
+ if (edit && edit->psys == psys)
+ draw_update_ptcache_edit(scene, ob, edit);
+ }
+
+ draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag);
+ }
+ invert_m4_m4(ob->imat, ob->obmat);
+ view3d_cached_text_draw_end(v3d, ar, 0, NULL);
+
+ glMultMatrixf(ob->obmat);
+
+ //glDepthMask(GL_TRUE);
+ if (col) cpack(col);
+ }
+
+ /* draw edit particles last so that they can draw over child particles */
+ if ((dflag & DRAW_PICKING) == 0 &&
+ (!scene->obedit))
+ {
+
+ if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
+ PTCacheEdit *edit = PE_create_current(scene, ob);
+ if (edit) {
+ glLoadMatrixf(rv3d->viewmat);
+ draw_update_ptcache_edit(scene, ob, edit);
+ draw_ptcache_edit(scene, v3d, edit);
+ glMultMatrixf(ob->obmat);
+ }
+ }
+ }
+
/* draw code for smoke, only draw domains */
if (smd && smd->domain) {
SmokeDomainSettings *sds = smd->domain;
- const bool show_smoke = true; /* XXX was checking cached frame range before */
+ const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe);
float viewnormal[3];
glLoadMatrixf(rv3d->viewmat);
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 584f442bd44..27ecbf83db5 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -32,7 +32,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_smoke_types.h"
@@ -43,6 +42,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_texture.h"
+#include "BKE_particle.h"
#include "smoke_API.h"
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 4526d120923..90fa54c7a16 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -878,6 +878,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_MODIFIER:
case ND_CONSTRAINT:
case ND_KEYS:
+ case ND_PARTICLE:
case ND_LOD:
ED_region_tag_redraw(ar);
break;
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 7193ce1b3cd..639be36d739 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -429,6 +429,11 @@ static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d
{
/* do nothing */
}
+ else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
+ V3D_IS_ZBUF(v3d))
+ {
+ /* do nothing */
+ }
else if (scene->obedit &&
V3D_IS_ZBUF(v3d))
{
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 6f45013ce42..620bbf03f32 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -71,6 +71,7 @@
#include "RNA_define.h"
#include "ED_armature.h"
+#include "ED_particle.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -3078,6 +3079,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
}
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ ok = PE_minmax(scene, min, max);
+ }
else if (ob &&
(ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
{
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 32e265cb981..ab0cae6822b 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -347,7 +347,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
/* Manipulators aren't used in paint modes */
- if (ob->mode != OB_MODE_SCULPT) {
+ if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
/* masks aren't used for sculpt and particle painting */
PointerRNA meshptr;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 73af8377d41..504a8383a41 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -280,7 +280,7 @@ void ED_view3d_cameracontrol_update(
void ED_view3d_cameracontrol_release(
struct View3DCameraControl *vctrl,
const bool restore);
-struct Object *ED_view3d_cameracontrol_object_get(
+Object *ED_view3d_cameracontrol_object_get(
struct View3DCameraControl *vctrl);
/* view3d_toolbar.c */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index f77e836461c..3239d07553f 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -85,6 +85,7 @@
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_particle.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -835,6 +836,8 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc,
else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
/* pass */
}
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT))
+ PE_lasso_select(C, mcords, moves, extend, select);
else {
do_lasso_select_objects(vc, mcords, moves, extend, select);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
@@ -2170,6 +2173,9 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
ret = do_paintvert_box_select(&vc, &rect, select, extend);
}
+ else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
+ ret = PE_border_select(C, &rect, select, extend);
+ }
else { /* object mode with none active */
ret = do_object_pose_box_select(C, &vc, &rect, select, extend);
}
@@ -2300,6 +2306,8 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
}
+ else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
+ return PE_mouse_particles(C, location, extend, deselect, toggle);
else if (obact && BKE_paint_select_face_test(obact))
retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
else if (BKE_paint_select_vert_test(obact))
@@ -2815,7 +2823,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
RNA_int_get(op->ptr, "y")};
if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) ||
- (obact && (obact->mode & OB_MODE_POSE)) )
+ (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
{
ViewContext vc;
@@ -2837,6 +2845,8 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else if (obact->mode & OB_MODE_POSE)
pose_circle_select(&vc, select, mval, (float)radius);
+ else
+ return PE_circle_select(C, select, mval, (float)radius);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
return OPERATOR_CANCELLED;