static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
{
	ParticleThreadContext *ctx= thread->ctx;
	int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */

	/* TODO_PARTICLE - use original index */
	pa->num= ctx->index[p];
	pa->fuv[0] = 1.0f;
	pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
	
#if ONLY_WORKING_WITH_PA_VERTS
	if (ctx->tree) {
		KDTreeNearest ptn[3];
		int w, maxw;
		
		psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
		BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
		maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
		
		for (w=0; w<maxw; w++) {
			pa->verts[w]=ptn->num;
		}
	}
#endif
	
	if (rng_skip_tot > 0) /* should never be below zero */
		BLI_rng_skip(thread->rng, rng_skip_tot);
}
Exemplo n.º 2
0
static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
{
	ParticleThreadContext *ctx= thread->ctx;
	MFace *mface;

	mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE);

	int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */

	/* TODO_PARTICLE - use original index */
	pa->num = ctx->index[p];

	zero_v4(pa->fuv);

	if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->dm->getNumVerts(ctx->dm)) {

		/* This finds the first face to contain the emitting vertex,
		 * this is not ideal, but is mostly fine as UV seams generally
		 * map to equal-colored parts of a texture */
		for (int i = 0; i < ctx->dm->getNumTessFaces(ctx->dm); i++, mface++) {
			if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) {
				unsigned int *vert = &mface->v1;

				for (int j = 0; j < 4; j++, vert++) {
					if (*vert == pa->num) {
						pa->fuv[j] = 1.0f;
						break;
					}
				}

				break;
			}
		}
	}

#if ONLY_WORKING_WITH_PA_VERTS
	if (ctx->tree) {
		KDTreeNearest ptn[3];
		int w, maxw;

		psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
		BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
		maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);

		for (w=0; w<maxw; w++) {
			pa->verts[w]=ptn->num;
		}
	}
#endif

	if (rng_skip_tot > 0) /* should never be below zero */
		BLI_rng_skip(thread->rng, rng_skip_tot);
}
Exemplo n.º 3
0
static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) {
	ParticleThreadContext *ctx= thread->ctx;
	DerivedMesh *dm= ctx->dm;
	float randu, randv;
	int distr= ctx->distr;
	int i;
	int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */

	MFace *mface;

	pa->num = i = ctx->index[p];
	mface = dm->getTessFaceData(dm,i,CD_MFACE);

	switch (distr) {
		case PART_DISTR_JIT:
			if (ctx->jitlevel == 1) {
				if (mface->v4)
					psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
				else
					psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
			}
			else {
				float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
				if (!isnan(offset)) {
					psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
				}
			}
			break;
		case PART_DISTR_RAND:
			randu= BLI_rng_get_float(thread->rng);
			randv= BLI_rng_get_float(thread->rng);
			rng_skip_tot -= 2;

			psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
			break;
	}
	pa->foffset= 0.0f;

	if (rng_skip_tot > 0) /* should never be below zero */
		BLI_rng_skip(thread->rng, rng_skip_tot);
}
Exemplo n.º 4
0
static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) {
	ParticleThreadContext *ctx= thread->ctx;
	Object *ob= ctx->sim.ob;
	DerivedMesh *dm= ctx->dm;
	float orco1[3], co1[3], nor1[3];
	float randu, randv;
	int cfrom= ctx->cfrom;
	int i;
	int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */

	MFace *mf;

	if (ctx->index[p] < 0) {
		cpa->num=0;
		cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
		cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
		return;
	}

	mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);

	randu= BLI_rng_get_float(thread->rng);
	randv= BLI_rng_get_float(thread->rng);
	rng_skip_tot -= 2;

	psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);

	cpa->num = ctx->index[p];

	if (ctx->tree) {
		KDTreeNearest ptn[10];
		int w,maxw;//, do_seams;
		float maxd /*, mind,dd */, totw= 0.0f;
		int parent[10];
		float pweight[10];

		psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
		BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
		maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);

		maxd=ptn[maxw-1].dist;
		/* mind=ptn[0].dist; */ /* UNUSED */

		/* the weights here could be done better */
		for (w=0; w<maxw; w++) {
			parent[w]=ptn[w].index;
			pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
		}
		for (;w<10; w++) {
			parent[w]=-1;
			pweight[w]=0.0f;
		}

		for (w=0,i=0; w<maxw && i<4; w++) {
			if (parent[w]>=0) {
				cpa->pa[i]=parent[w];
				cpa->w[i]=pweight[w];
				totw+=pweight[w];
				i++;
			}
		}
		for (;i<4; i++) {
			cpa->pa[i]=-1;
			cpa->w[i]=0.0f;
		}

		if (totw > 0.0f) {
			for (w = 0; w < 4; w++) {
				cpa->w[w] /= totw;
			}
		}

		cpa->parent=cpa->pa[0];
	}

	if (rng_skip_tot > 0) /* should never be below zero */
		BLI_rng_skip(thread->rng, rng_skip_tot);
}
Exemplo n.º 5
0
static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) {
	ParticleThreadContext *ctx= thread->ctx;
	DerivedMesh *dm= ctx->dm;
	float *v1, *v2, *v3, *v4, nor[3], co[3];
	float cur_d, min_d, randu, randv;
	int distr= ctx->distr;
	int i, intersect, tot;
	int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */

	MFace *mface;
	MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);

	pa->num = i = ctx->index[p];
	mface = dm->getTessFaceData(dm,i,CD_MFACE);

	switch (distr) {
		case PART_DISTR_JIT:
			if (ctx->jitlevel == 1) {
				if (mface->v4)
					psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
				else
					psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
			}
			else {
				float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
				if (!isnan(offset)) {
					psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
				}
			}
			break;
		case PART_DISTR_RAND:
			randu= BLI_rng_get_float(thread->rng);
			randv= BLI_rng_get_float(thread->rng);
			rng_skip_tot -= 2;

			psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
			break;
	}
	pa->foffset= 0.0f;

	/* experimental */
	tot=dm->getNumTessFaces(dm);

	psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0);

	normalize_v3(nor);
	negate_v3(nor);

	min_d=FLT_MAX;
	intersect=0;

	for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++) {
		if (i==pa->num) continue;

		v1=mvert[mface->v1].co;
		v2=mvert[mface->v2].co;
		v3=mvert[mface->v3].co;

		if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) {
			if (cur_d<min_d) {
				min_d=cur_d;
				pa->foffset=cur_d*0.5f; /* to the middle of volume */
				intersect=1;
			}
		}
		if (mface->v4) {
			v4=mvert[mface->v4].co;

			if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) {
				if (cur_d<min_d) {
					min_d=cur_d;
					pa->foffset=cur_d*0.5f; /* to the middle of volume */
					intersect=1;
				}
			}
		}
	}
	if (intersect==0)
		pa->foffset=0.0;
	else {
		switch (distr) {
			case PART_DISTR_JIT:
				pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
				break;
			case PART_DISTR_RAND:
				pa->foffset *= BLI_frand();
				break;
		}
	}

	if (rng_skip_tot > 0) /* should never be below zero */
		BLI_rng_skip(thread->rng, rng_skip_tot);
}