static bool depth_read_normal( const ViewContext *vc, const bglMats *mats, const int mval[2], float r_normal[3]) { /* pixels surrounding */ bool depths_valid[9] = {false}; float coords[9][3] = {{0}}; ARegion *ar = vc->ar; const ViewDepths *depths = vc->rv3d->depths; for (int x = 0, i = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)}; const double depth = (double)depth_read_zbuf(vc, mval_ofs[0], mval_ofs[1]); if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { if (depth_unproject(ar, mats, mval_ofs, depth, coords[i])) { depths_valid[i] = true; } } i++; } } const int edges[2][6][2] = { /* x edges */ {{0, 1}, {1, 2}, {3, 4}, {4, 5}, {6, 7}, {7, 8}}, /* y edges */ {{0, 3}, {3, 6}, {1, 4}, {4, 7}, {2, 5}, {5, 8}}, }; float cross[2][3] = {{0.0f}}; for (int i = 0; i < 6; i++) { for (int axis = 0; axis < 2; axis++) { if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) { float delta[3]; sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]); add_v3_v3(cross[axis], delta); } } } cross_v3_v3v3(r_normal, cross[0], cross[1]); if (normalize_v3(r_normal) != 0.0f) { return true; } else { return false; } }
void BLI_mirrorAlongAxis(float v[3], float center[3], float axis[3]) { float dv[3], pv[3]; sub_v3_v3v3(dv, v, center); project_v3_v3v3(pv, dv, axis); mul_v3_fl(pv, -2); add_v3_v3(v, pv); }
static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa) { KDTreeNearest *ptn = NULL; ParticleTarget *pt; float len = 2.0f * val->personal_space * pa->size + 1.0f; float vec[3] = {0.0f, 0.0f, 0.0f}; int neighbors = BLI_kdtree_range_search( bbd->sim->psys->tree, pa->prev_state.co, &ptn, 2.0f * val->personal_space * pa->size); int ret = 0; if (neighbors > 1 && ptn[1].dist!=0.0f) { sub_v3_v3v3(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co); mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist); add_v3_v3(bbd->wanted_co, vec); bbd->wanted_speed = val->max_speed; len = ptn[1].dist; ret = 1; } if (ptn) { MEM_freeN(ptn); ptn=NULL; } /* check other boid systems */ for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if (epsys) { neighbors = BLI_kdtree_range_search( epsys->tree, pa->prev_state.co, &ptn, 2.0f * val->personal_space * pa->size); if (neighbors > 0 && ptn[0].dist < len) { sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co); mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[0].dist) / ptn[1].dist); add_v3_v3(bbd->wanted_co, vec); bbd->wanted_speed = val->max_speed; len = ptn[0].dist; ret = 1; } if (ptn) { MEM_freeN(ptn); ptn=NULL; } } } return ret; }
/* this makes sure we can extend for non-cyclic. * * returns OK: 1/0 */ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius) { Curve *cu = ob->data; BevList *bl; float ctime1; int cycl = 0; /* test for cyclic */ bl = cu->bev.first; if (!bl->nr) return 0; if (bl && bl->poly > -1) cycl = 1; if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); } else ctime1 = ctime; /* vec needs 4 items */ if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if (cycl == 0) { Path *path = cu->path; float dvec[3]; if (ctime < 0.0f) { sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec); mul_v3_fl(dvec, ctime * (float)path->len); add_v3_v3(vec, dvec); if (quat) copy_qt_qt(quat, path->data[0].quat); if (radius) *radius = path->data[0].radius; } else if (ctime > 1.0f) { sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec); mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len); add_v3_v3(vec, dvec); if (quat) copy_qt_qt(quat, path->data[path->len - 1].quat); if (radius) *radius = path->data[path->len - 1].radius; /* weight - not used but could be added */ } } return 1; } return 0; }
static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone) { float selboneaxis[3], actboneaxis[3], length; sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head); normalize_v3(actboneaxis); sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head); length = len_v3(selboneaxis); mul_v3_fl(actboneaxis, length); add_v3_v3v3(selbone->tail, selbone->head, actboneaxis); selbone->roll = actbone->roll; /* if the bone being aligned has connected descendants they must be moved * according to their parent new position, otherwise they would be left * in an inconsistent state: connected but away from the parent*/ fix_editbone_connected_children(edbo, selbone); }
void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { float ed1[3], ed2[3], ed3[3], ed4[3]; sub_v3_v3v3(ed1, v4, v1); sub_v3_v3v3(ed2, v1, v2); sub_v3_v3v3(ed3, v2, v3); sub_v3_v3v3(ed4, v3, v4); normalize_v3(ed1); normalize_v3(ed2); normalize_v3(ed3); normalize_v3(ed4); angles[0] = (float)M_PI - angle_normalized_v3v3(ed1, ed2); angles[1] = (float)M_PI - angle_normalized_v3v3(ed2, ed3); angles[2] = (float)M_PI - angle_normalized_v3v3(ed3, ed4); angles[3] = (float)M_PI - angle_normalized_v3v3(ed4, ed1); }
/** ensure \a v1 is \a dist from \a v2 */ void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist) { if (!equals_v3v3(v2, v1)) { float nor[3]; sub_v3_v3v3(nor, v1, v2); normalize_v3(nor); madd_v3_v3v3fl(v1, v2, nor, dist); } }
static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time) { /* only called when strip has cyclic, so >= 1.0f works... */ if(time >= 1.0f) { bActionChannel *achan= get_action_channel(strip->act, strip->offs_bone); if(achan && achan->ipo) { IpoCurve *icu= NULL; Bone *bone; float min[3]={0.0f, 0.0f, 0.0f}, max[3]={0.0f, 0.0f, 0.0f}; int index=0, foundvert= 0; /* calculate the min/max */ for (icu=achan->ipo->curve.first; icu; icu=icu->next) { if(icu->totvert>1) { if(icu->adrcode==AC_LOC_X) index= 0; else if(icu->adrcode==AC_LOC_Y) index= 1; else if(icu->adrcode==AC_LOC_Z) index= 2; else continue; foundvert= 1; min[index]= icu->bezt[0].vec[1][1]; max[index]= icu->bezt[icu->totvert-1].vec[1][1]; } } if(foundvert) { /* bring it into armature space */ sub_v3_v3v3(min, max, min); bone= get_named_bone(ob->data, strip->offs_bone); /* weak */ if(bone) { mul_mat3_m4_v3(bone->arm_mat, min); /* dominant motion, cyclic_offset was cleared in rest_pose */ if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) { if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0]= time*min[0]; if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1]= time*min[1]; if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2]= time*min[2]; } else { if( fabs(min[0]) >= fabs(min[1]) && fabs(min[0]) >= fabs(min[2])) pose->cyclic_offset[0]= time*min[0]; else if( fabs(min[1]) >= fabs(min[0]) && fabs(min[1]) >= fabs(min[2])) pose->cyclic_offset[1]= time*min[1]; else pose->cyclic_offset[2]= time*min[2]; } } } } } }
static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2) { MDefBoundIsect *isect; MeshDeformIsect isec; float (*cagecos)[3]; MFace *mface; float vert[4][3], len, end[3]; static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4}; /* setup isec */ memset(&isec, 0, sizeof(isec)); isec.labda= 1e10f; VECADD(isec.start, co1, epsilon); VECADD(end, co2, epsilon); sub_v3_v3v3(isec.vec, end, isec.start); if(meshdeform_intersect(mdb, &isec)) { len= isec.labda; mface=(MFace*)isec.face; /* create MDefBoundIsect */ isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect)); /* compute intersection coordinate */ isect->co[0]= co1[0] + isec.vec[0]*len; isect->co[1]= co1[1] + isec.vec[1]*len; isect->co[2]= co1[2] + isec.vec[2]*len; isect->len= len_v3v3(co1, isect->co); if(isect->len < MESHDEFORM_LEN_THRESHOLD) isect->len= MESHDEFORM_LEN_THRESHOLD; isect->v[0]= mface->v1; isect->v[1]= mface->v2; isect->v[2]= mface->v3; isect->v[3]= mface->v4; isect->nvert= (mface->v4)? 4: 3; isect->facing= isec.isect; /* compute mean value coordinates for interpolation */ cagecos= mdb->cagecos; copy_v3_v3(vert[0], cagecos[mface->v1]); copy_v3_v3(vert[1], cagecos[mface->v2]); copy_v3_v3(vert[2], cagecos[mface->v3]); if(mface->v4) copy_v3_v3(vert[3], cagecos[mface->v4]); interp_weights_poly_v3( isect->uvw,vert, isect->nvert, isect->co); return isect; } return NULL; }
static void particle_system_minmax(Scene *scene, Object *object, ParticleSystem *psys, float radius, float min[3], float max[3]) { const float size[3] = {radius, radius, radius}; const float cfra = BKE_scene_frame_get(scene); ParticleSettings *part = psys->part; ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL; int i; int total_particles; float mat[4][4], imat[4][4]; INIT_MINMAX(min, max); if (part->type == PART_HAIR) { /* TOOD(sergey): Not supported currently. */ return; } unit_m4(mat); psys_render_set(object, psys, mat, mat, 1, 1, 0); sim.scene = scene; sim.ob = object; sim.psys = psys; sim.psmd = psys_get_modifier(object, psys); invert_m4_m4(imat, object->obmat); total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) { float co_object[3], co_min[3], co_max[3]; ParticleKey state; state.time = cfra; if (!psys_get_particle_state(&sim, i, &state, 0)) { continue; } mul_v3_m4v3(co_object, imat, state.co); sub_v3_v3v3(co_min, co_object, size); add_v3_v3v3(co_max, co_object, size); minmax_v3v3_v3(min, max, co_min); minmax_v3v3_v3(min, max, co_max); } if (psys->lattice_deform_data) { end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } psys_render_restore(object, psys); }
/* helper to fix a ebone position if its parent has moved due to alignment*/ static void fix_connected_bone(EditBone *ebone) { float diff[3]; if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head)) return; /* if the parent has moved we translate child's head and tail accordingly */ sub_v3_v3v3(diff, ebone->parent->tail, ebone->head); add_v3_v3(ebone->head, diff); add_v3_v3(ebone->tail, diff); }
/* project a vector on a plane defined by normal and a plane point p */ void project_v3_plane(float v[3], const float n[3], const float p[3]) { float vector[3]; float mul; sub_v3_v3v3(vector, v, p); mul = dot_v3v3(vector, n) / len_squared_v3(n); mul_v3_v3fl(vector, n, mul); sub_v3_v3(v, vector); }
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) { float d1[3], d2[3], len_d1; sub_v3_v3v3(d1, p1, t->center_global); sub_v3_v3v3(d2, p2, t->center_global); if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { mul_m3_v3(t->con.pmtx, d1); mul_m3_v3(t->con.pmtx, d2); } project_v3_v3v3(d1, d1, d2); len_d1 = len_v3(d1); /* Use 'invalid' dist when `center == p1` (after projecting), * in this case scale will _never_ move the point in relation to the center, * so it makes no sense to take it into account when scaling. see: T46503 */ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; }
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { DupliObject *dob; Group *group; GroupObject *go; float mat[4][4], tmat[4][4]; if (ob->dup_group==NULL) return; group= ob->dup_group; /* simple preventing of too deep nested groups */ if (level>MAX_DUPLI_RECUR) return; /* handles animated groups, and */ /* we need to check update for objects that are not in scene... */ group_handle_recalc_and_update(scene, ob, group); animated= animated || group_is_animated(ob, group); for (go= group->gobject.first; go; go= go->next) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if (go->ob!=ob) { /* group dupli offset, should apply after everything else */ if (!is_zero_v3(group->dupli_ofs)) { copy_m4_m4(tmat, go->ob->obmat); sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs); mult_m4_m4m4(mat, ob->obmat, tmat); } else { mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ( (dob->origlay & group->layer)==0 || (G.rendering==0 && dob->ob->restrictflag & OB_RESTRICT_VIEW) || (G.rendering && dob->ob->restrictflag & OB_RESTRICT_RENDER) ) { dob->no_draw= 1; } else { dob->no_draw= 0; } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level+1, animated); copy_m4_m4(dob->ob->obmat, dob->omat); } } } }
static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; LinkNode *search = NULL; float hair_frame[3][3], dir_old[3], dir_new[3]; int prev_mn; /* to find hair roots */ if (!clmd->hairdata) return; /* XXX Note: we need to propagate frames from the root up, * but structural hair springs are stored in reverse order. * The bending springs however are then inserted in the same * order as vertices again ... * This messy situation can be resolved when solver data is * generated directly from a dedicated hair system. */ prev_mn = -1; for (search = cloth->springs; search; search = search->next) { ClothSpring *spring = search->link; ClothHairData *hair_ij, *hair_kl; bool is_root = spring->kl != prev_mn; if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) { continue; } hair_ij = &clmd->hairdata[spring->ij]; hair_kl = &clmd->hairdata[spring->kl]; if (is_root) { /* initial hair frame from root orientation */ copy_m3_m3(hair_frame, hair_ij->rot); /* surface normal is the initial direction, * parallel transport then keeps it aligned to the hair direction */ copy_v3_v3(dir_new, hair_frame[2]); } copy_v3_v3(dir_old, dir_new); sub_v3_v3v3(dir_new, cloth->verts[spring->mn].xrest, cloth->verts[spring->kl].xrest); normalize_v3(dir_new); /* dir expressed in the hair frame defines the rest target direction */ copy_v3_v3(hair_kl->rest_target, dir_new); mul_transposed_m3_v3(hair_frame, hair_kl->rest_target); /* move frame to next hair segment */ cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new); prev_mn = spring->mn; } }
float distPointToSegmentSq(const float* point, const float* a, const float* b) { float abx[3], dx[3]; float d, t; sub_v3_v3v3(abx, b,a); sub_v3_v3v3(dx, point,a); d = abx[0]*abx[0]+abx[2]*abx[2]; t = abx[0]*dx[0]+abx[2]*dx[2]; if (d > 0) t /= d; if (t < 0) t = 0; else if (t > 1) t = 1; dx[0] = a[0] + t*abx[0] - point[0]; dx[2] = a[2] + t*abx[2] - point[2]; return dx[0]*dx[0] + dx[2]*dx[2]; }
/* XXX, could replace with #dist_to_line_segment_v3(), or add a squared version */ float distPointToSegmentSq(const float point[3], const float a[3], const float b[3]) { float abx[3], dx[3]; float d, t; sub_v3_v3v3(abx, b, a); sub_v3_v3v3(dx, point, a); d = abx[0] * abx[0] + abx[2] * abx[2]; t = abx[0] * dx[0] + abx[2] * dx[2]; if (d > 0.0f) t /= d; if (t < 0.0f) t = 0.0f; else if (t > 1.0f) t = 1.0f; dx[0] = a[0] + t * abx[0] - point[0]; dx[2] = a[2] + t * abx[2] - point[2]; return dx[0] * dx[0] + dx[2] * dx[2]; }
static void do_twist(const ParticleChildModifierContext *modifier_ctx, ParticleKey *state, const float time) { ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx; ParticleSimulationData *sim = modifier_ctx->sim; ParticleTexture *ptex = modifier_ctx->ptex; ParticleSettings *part = sim->psys->part; /* Early output checks. */ if (modifier_ctx->parent_keys == NULL) { /* Cannot get axis of rotation... */ return; } if (part->childtype != PART_CHILD_PARTICLES) { /* Interpolated children behave weird with twist. */ return; } if (part->twist == 0.0f) { /* No twist along the strand. */ return; } /* Dependent on whether it's threaded update or not, curve comes * from different places. */ CurveMapping *twist_curve = NULL; if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) { twist_curve = (thread_ctx != NULL) ? thread_ctx->twistcurve : part->twistcurve; } /* Axis of rotation. */ float axis[3]; twist_get_axis(modifier_ctx, time, axis); /* Angle of rotation. */ float angle = part->twist; if (ptex != NULL) { angle *= (ptex->twist - 0.5f) * 2.0f; } if (twist_curve != NULL) { const int num_segments = twist_num_segments(modifier_ctx); angle *= curvemapping_integrate_clamped(twist_curve, 0.0f, time, 1.0f / num_segments); } else { angle *= time; } /* Perform rotation around parent curve. */ float vec[3]; sub_v3_v3v3(vec, state->co, modifier_ctx->par_co); rotate_v3_v3v3fl(state->co, vec, axis, angle * 2.0f * M_PI); add_v3_v3(state->co, modifier_ctx->par_co); }
/* tracing */ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) { float visibility = 1.f; if (lar->shb) { float dxco[3] = {0.f, 0.f, 0.f}, dyco[3] = {0.f, 0.f, 0.f}; visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); } else if (lar->mode & LA_SHAD_RAY) { /* trace shadow manually, no good lamp api atm */ Isect is; copy_v3_v3(is.start, co); if (lar->type == LA_SUN || lar->type == LA_HEMI) { is.dir[0] = -lar->vec[0]; is.dir[1] = -lar->vec[1]; is.dir[2] = -lar->vec[2]; is.dist = R.maxdist; } else { sub_v3_v3v3(is.dir, lar->co, is.start); is.dist = normalize_v3(is.dir); } is.mode = RE_RAY_MIRROR; is.check = RE_CHECK_VLR_NON_SOLID_MATERIAL; is.skip = 0; if (lar->mode & (LA_LAYER | LA_LAYER_SHADOW)) is.lay = lar->lay; else is.lay = -1; is.orig.ob = NULL; is.orig.face = NULL; is.last_hit = lar->last_hit[shi->thread]; RE_instance_rotate_ray(shi->obi, &is); if (RE_rayobject_raycast(R.raytree, &is)) { RE_instance_rotate_ray_restore(shi->obi, &is); visibility = 0.f; } lar->last_hit[shi->thread] = is.last_hit; } return visibility; }
static void rna_EditBone_matrix_get(PointerRNA *ptr, float *values) { EditBone *ebone = (EditBone *)(ptr->data); float delta[3], tmat[3][3], mat[4][4]; /* Find the current bone matrix */ sub_v3_v3v3(delta, ebone->tail, ebone->head); vec_roll_to_mat3(delta, ebone->roll, tmat); copy_m4_m3(mat, tmat); copy_v3_v3(mat[3], ebone->head); memcpy(values, mat, 16 * sizeof(float)); }
static void flagAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc, int group) { float vec[3]; arc->symmetry_group = group; sub_v3_v3v3(vec, end_node->p, root_node->p); if (dot_v3v3(vec, root_node->symmetry_axis) < 0) { arc->symmetry_flag |= SYM_SIDE_NEGATIVE; } else { arc->symmetry_flag |= SYM_SIDE_POSITIVE; } }
static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *key, float max_length, float step_length, float *cur_length, float dvec[3]) { if (*cur_length + step_length > max_length) { sub_v3_v3v3(dvec, key->co, (key-1)->co); mul_v3_fl(dvec, (max_length - *cur_length) / step_length); add_v3_v3v3(key->co, (key-1)->co, dvec); keys->segments = k; /* something over the maximum step value */ return false; } else { *cur_length += step_length; return true; } }
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source) { float closest[3], d[3], dist, cosine; /* compute euclidian distance */ closest_to_line_segment_v3(closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]); sub_v3_v3v3(d, sys->heat.verts[vertex], closest); dist = normalize_v3(d); /* if the vertex normal does not point along the bone, increase distance */ cosine = dot_v3v3(d, sys->heat.vnors[vertex]); return dist / (0.5f * (cosine + 1.001f)); }
BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *bmtree, const float co_a[3], const float co_b[3], float *r_fac, float r_hitout[3], float r_cagehit[3]) { BVHTreeRayHit hit; struct SegmentUserData bmcb_data; const float dist = len_v3v3(co_a, co_b); float dir[3]; if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT)); sub_v3_v3v3(dir, co_b, co_a); hit.dist = dist; hit.index = -1; /* ok to leave 'uv' uninitialized */ bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->looptris; bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage; bmcb_data.co_a = co_a; bmcb_data.co_b = co_b; BLI_bvhtree_ray_cast(bmtree->tree, co_a, dir, 0.0f, &hit, bmbvh_find_face_segment_cb, &bmcb_data); if (hit.index != -1 && hit.dist != dist) { /* duplicate of BKE_bmbvh_ray_cast() */ if (r_hitout) { if (bmtree->flag & BMBVH_RETURN_ORIG) { BMLoop **ltri = bmtree->looptris[hit.index]; interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data.uv); } else { copy_v3_v3(r_hitout, hit.co); } if (r_cagehit) { copy_v3_v3(r_cagehit, hit.co); } } /* end duplicate */ if (r_fac) { *r_fac = hit.dist / dist; } return bmtree->looptris[hit.index][0]->f; } return NULL; }
static void ApplySnapTranslation(TransInfo *t, float vec[3]) { float point[3]; getSnapPoint(t, point); if (t->spacetype == SPACE_NODE) { char border = t->tsnap.snapNodeBorder; if (border & (NODE_LEFT | NODE_RIGHT)) vec[0] = point[0] - t->tsnap.snapTarget[0]; if (border & (NODE_BOTTOM | NODE_TOP)) vec[1] = point[1] - t->tsnap.snapTarget[1]; } else { sub_v3_v3v3(vec, point, t->tsnap.snapTarget); } }
static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode) { EditBone *ebone; float offset[3]; if ((selbone->parent) && (selbone->flag & BONE_CONNECTED)) selbone->parent->flag &= ~(BONE_TIPSEL); /* make actbone the parent of selbone */ selbone->parent = actbone; /* in actbone tree we cannot have a loop */ for (ebone = actbone->parent; ebone; ebone = ebone->parent) { if (ebone->parent == selbone) { ebone->parent = NULL; ebone->flag &= ~BONE_CONNECTED; } } if (mode == ARM_PAR_CONNECT) { /* Connected: Child bones will be moved to the parent tip */ selbone->flag |= BONE_CONNECTED; sub_v3_v3v3(offset, actbone->tail, selbone->head); copy_v3_v3(selbone->head, actbone->tail); selbone->rad_head = actbone->rad_tail; add_v3_v3(selbone->tail, offset); /* offset for all its children */ for (ebone = edbo->first; ebone; ebone = ebone->next) { EditBone *par; for (par = ebone->parent; par; par = par->parent) { if (par == selbone) { add_v3_v3(ebone->head, offset); add_v3_v3(ebone->tail, offset); break; } } } } else { /* Offset: Child bones will retain their distance from the parent tip */ selbone->flag &= ~BONE_CONNECTED; } }
static void multires_reshape_vertex_from_final_data(MultiresReshapeContext *ctx, const int ptex_face_index, const float corner_u, const float corner_v, const int coarse_poly_index, const int coarse_corner, const float final_P[3], const float final_mask) { Subdiv *subdiv = ctx->subdiv; const int grid_size = ctx->top_grid_size; const Mesh *coarse_mesh = ctx->coarse_mesh; const MPoly *coarse_mpoly = coarse_mesh->mpoly; const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index]; const int loop_index = coarse_poly->loopstart + coarse_corner; /* Evaluate limit surface. */ float P[3], dPdu[3], dPdv[3]; multires_reshape_sample_surface( subdiv, coarse_poly, coarse_corner, corner_u, corner_v, ptex_face_index, P, dPdu, dPdv); /* Construct tangent matrix which matches orientation of the current * displacement grid. */ float tangent_matrix[3][3], inv_tangent_matrix[3][3]; multires_reshape_tangent_matrix_for_corner( coarse_poly, coarse_corner, dPdu, dPdv, tangent_matrix); invert_m3_m3(inv_tangent_matrix, tangent_matrix); /* Convert object coordinate to a tangent space of displacement grid. */ float D[3]; sub_v3_v3v3(D, final_P, P); float tangent_D[3]; mul_v3_m3v3(tangent_D, inv_tangent_matrix, D); /* Calculate index of element within the grid. */ float grid_u, grid_v; BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v); const int grid_x = (grid_u * (grid_size - 1) + 0.5f); const int grid_y = (grid_v * (grid_size - 1) + 0.5f); const int index = grid_y * grid_size + grid_x; /* Write tangent displacement. */ MDisps *displacement_grid = &ctx->mdisps[loop_index]; copy_v3_v3(displacement_grid->disps[index], tangent_D); /* Write mask grid. */ if (ctx->grid_paint_mask != NULL) { GridPaintMask *grid_paint_mask = &ctx->grid_paint_mask[loop_index]; BLI_assert(grid_paint_mask->level == displacement_grid->level); grid_paint_mask->data[index] = final_mask; } }
/* get the camera's dof value, takes the dof object into account */ float BKE_camera_object_dof_distance(Object *ob) { Camera *cam = (Camera *)ob->data; if (ob->type != OB_CAMERA) return 0.0f; if (cam->dof_ob) { #if 0 /* too simple, better to return the distance on the view axis only */ return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); #else float view_dir[3], dof_dir[3]; normalize_v3_v3(view_dir, ob->obmat[2]); sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof_ob->obmat[3]); return fabsf(dot_v3v3(view_dir, dof_dir)); #endif } return cam->YF_dofdist; }
static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor) { BoidParticle *bpa = pa->boid; float nor[3], vel[3]; copy_v3_v3(nor, surface_nor); /* gather apparent gravity */ madd_v3_v3fl(bpa->gravity, surface_nor, -1.0f); normalize_v3(bpa->gravity); /* raise boid it's size from surface */ mul_v3_fl(nor, pa->size * boids->height); add_v3_v3v3(pa->state.co, surface_co, nor); /* remove normal component from velocity */ project_v3_v3v3(vel, pa->state.vel, surface_nor); sub_v3_v3v3(pa->state.vel, pa->state.vel, vel); }
static void rigid_add_half_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w) { /* formula (8) */ float Rsum[3][3], rhs[3]; if (sys->vpinned[v1->tmp.l]) return; add_m3_m3m3(Rsum, sys->rigid.R[v1->tmp.l], sys->rigid.R[v2->tmp.l]); transpose_m3(Rsum); sub_v3_v3v3(rhs, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]); mul_m3_v3(Rsum, rhs); mul_v3_fl(rhs, 0.5f); mul_v3_fl(rhs, w); add_v3_v3(sys->rigid.rhs[v1->tmp.l], rhs); }