static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) { BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata; MFace *mf = data->sys->heat.mface + index; float (*verts)[3] = data->sys->heat.verts; float lambda, uv[2], n[3], dir[3]; mul_v3_v3fl(dir, data->vec, hit->dist); if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v2], verts[mf->v3], &lambda, uv)) { normal_tri_v3(n, verts[mf->v1], verts[mf->v2], verts[mf->v3]); if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) { hit->index = index; hit->dist *= lambda; } } mul_v3_v3fl(dir, data->vec, hit->dist); if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v3], verts[mf->v4], &lambda, uv)) { normal_tri_v3(n, verts[mf->v1], verts[mf->v3], verts[mf->v4]); if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) { hit->index = index; hit->dist *= lambda; } } }
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata; const MLoopTri *lt = &data->sys->heat.mlooptri[index]; const MLoop *mloop = data->sys->heat.mloop; float (*verts)[3] = data->sys->heat.verts; const float *vtri_co[3]; float dist_test; vtri_co[0] = verts[mloop[lt->tri[0]].v]; vtri_co[1] = verts[mloop[lt->tri[1]].v]; vtri_co[2] = verts[mloop[lt->tri[2]].v]; #ifdef USE_KDOPBVH_WATERTIGHT if (isect_ray_tri_watertight_v3(data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL)) #else UNUSED_VARS(ray); if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL)) #endif { if (dist_test < hit->dist) { float n[3]; normal_tri_v3(n, UNPACK3(vtri_co)); if (dot_v3v3(n, data->vec) < -1e-5f) { hit->index = index; hit->dist = dist_test; } } } }
static void bmbvh_find_face_segment_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { struct SegmentUserData *bmcb_data = userdata; const BMLoop **ltri = bmcb_data->looptris[index]; float dist, uv[2]; const float *tri_cos[3]; bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); if (equals_v3v3(bmcb_data->co_a, tri_cos[0]) || equals_v3v3(bmcb_data->co_a, tri_cos[1]) || equals_v3v3(bmcb_data->co_a, tri_cos[2]) || equals_v3v3(bmcb_data->co_b, tri_cos[0]) || equals_v3v3(bmcb_data->co_b, tri_cos[1]) || equals_v3v3(bmcb_data->co_b, tri_cos[2])) { return; } if (isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv) && (dist < hit->dist)) { hit->dist = dist; hit->index = index; copy_v3_v3(hit->no, ltri[0]->f->no); madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist); copy_v2_v2(bmcb_data->uv, uv); } }
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { struct RayCastUserData *bmcb_data = userdata; const BMLoop **ltri = bmcb_data->looptris[index]; float dist, uv[2]; const float *tri_cos[3]; bool isect; bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); isect = (ray->radius > 0.0f ? isect_ray_tri_epsilon_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv, ray->radius) : isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv)); if (isect && dist < hit->dist) { hit->dist = dist; hit->index = index; copy_v3_v3(hit->no, ltri[0]->f->no); madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist); copy_v2_v2(bmcb_data->uv, uv); } }
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { struct RayCastUserData *bmcb_data = userdata; const BMLoop **ltri = bmcb_data->looptris[index]; float dist, uv[2]; const float *tri_cos[3]; bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); if (isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv) && (dist < hit->dist)) { hit->dist = dist; hit->index = index; copy_v3_v3(hit->no, ltri[0]->f->no); copy_v3_v3(hit->co, ray->direction); normalize_v3(hit->co); mul_v3_fl(hit->co, dist); add_v3_v3(hit->co, ray->origin); copy_v2_v2(bmcb_data->uv, uv); } }
static float ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float *v0, const float *v1, const float *v2) { float dist; if(isect_ray_tri_v3((float*)ray->origin, (float*)ray->direction, (float*)v0, (float*)v1, (float*)v2, &dist, NULL)) return dist; return FLT_MAX; }
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); }