/* create intersection coordinates in view Z direction at mouse coordinates */ void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d= ar->regiondata; if(rv3d->is_persp) { float vec[3]; ED_view3d_win_to_vector(ar, mval, vec); copy_v3_v3(ray_start, rv3d->viewinv[3]); VECADDFAC(ray_start, rv3d->viewinv[3], vec, v3d->near); VECADDFAC(ray_end, rv3d->viewinv[3], vec, v3d->far); } else { float vec[4]; vec[0] = 2.0f * mval[0] / ar->winx - 1; vec[1] = 2.0f * mval[1] / ar->winy - 1; vec[2] = 0.0f; vec[3] = 1.0f; mul_m4_v4(rv3d->persinv, vec); VECADDFAC(ray_start, vec, rv3d->viewinv[2], 1000.0f); VECADDFAC(ray_end, vec, rv3d->viewinv[2], -1000.0f); } /* clipping */ if(rv3d->rflag & RV3D_CLIPPING) { int a; for(a=0; a<4; a++) { clip_line_plane(ray_start, ray_end, rv3d->clip[a]); } } }
/* options that can be passed: * BME_BEVEL_VWEIGHT <---- v, Look at vertex weights; use defgrp_index if option is present * BME_BEVEL_SELECT <---- v,e, check selection for verts and edges * BME_BEVEL_ANGLE <---- v,e, don't bevel-tag verts - tag verts per edge * BME_BEVEL_VERT <---- e, don't tag edges * BME_BEVEL_EWEIGHT <---- e, use crease flag for now * BME_BEVEL_PERCENT <---- Will need to think about this one; will probably need to incorporate into actual bevel routine * BME_BEVEL_RADIUS <---- Will need to think about this one; will probably need to incorporate into actual bevel routine * All weights/limits are stored per-vertex */ BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) { BME_Vert *v; BME_TransData_Head *td; BME_TransData *vtd; int i; float fac=1, d; td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); BME_bevel_initialize(bm, options, defgrp_index, angle, td); /* recursion math courtesy of Martin Poirier (theeth) */ for (i=0; i<res-1; i++) { if (i==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * i * 2.0f); } d = 1.0f/fac; /* crazy idea. if res == 0, don't remove original geometry */ for (i=0; i<res || (res==0 && i==0); i++) { if (i != 0) BME_bevel_reinitialize(bm); BME_model_begin(bm); BME_bevel_mesh(bm,d,res,options,defgrp_index,td); BME_model_end(bm); if (i==0) d /= 3; else d /= 2; } BME_tesselate(bm); if (rtd) { *rtd = td; return bm; } /* transform pass */ for (v = bm->verts.first; v; v=v->next) { if ( (vtd = BME_get_transdata(td, v)) ) { if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) { d = *vtd->max; } else { d = value; } VECADDFAC(v->co,vtd->org,vtd->vec,vtd->factor*d); } v->tflag1 = 0; } BME_free_transdata(td); return bm; }
static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float *v0, const float *v1, const float *v2) { float idist; float p1[3]; float plane_normal[3], hit_point[3]; normal_tri_v3( plane_normal,(float*)v0, (float*)v1, (float*)v2); VECADDFAC( p1, ray->origin, ray->direction, m_dist); if(isect_sweeping_sphere_tri_v3((float*)ray->origin, p1, radius, (float*)v0, (float*)v1, (float*)v2, &idist, hit_point)) { return idist * m_dist; } return FLT_MAX; }
float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights) { float temp[3]; float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; float fac, r_fac; fac = dot_v3v3(efd->nor, efd->vec_to_point2); if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) falloff=0.0f; else if(eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f) falloff=0.0f; else switch(eff->pd->falloff){ case PFIELD_FALL_SPHERE: falloff*= falloff_func_dist(eff->pd, efd->distance); break; case PFIELD_FALL_TUBE: falloff*= falloff_func_dist(eff->pd, ABS(fac)); if(falloff == 0.0f) break; VECADDFAC(temp, efd->vec_to_point, efd->nor, -fac); r_fac= len_v3(temp); falloff*= falloff_func_rad(eff->pd, r_fac); break; case PFIELD_FALL_CONE: falloff*= falloff_func_dist(eff->pd, ABS(fac)); if(falloff == 0.0f) break; r_fac= RAD2DEGF(saacos(fac/len_v3(efd->vec_to_point))); falloff*= falloff_func_rad(eff->pd, r_fac); break; } return falloff; }
/* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/ static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) { BME_Vert *nv, *v2; float len; v2 = BME_edge_getothervert(e,v); nv = BME_SEMV(bm,v,e,ne); if (nv == NULL) return NULL; VECSUB(nv->co,v2->co,v->co); len = len_v3(nv->co); VECADDFAC(nv->co,v->co,nv->co,len*percent); nv->flag = v->flag; nv->bweight = v->bweight; if (ne) { (*ne)->flag = e->flag; (*ne)->h = e->h; (*ne)->crease = e->crease; (*ne)->bweight = e->bweight; } /*v->nv->v2*/ BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75); return nv; }
// Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces. // userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; MVert *vert = data->vert; MFace *face = data->face + index; float *t0, *t1, *t2, *t3; t0 = vert[ face->v1 ].co; t1 = vert[ face->v2 ].co; t2 = vert[ face->v3 ].co; t3 = face->v4 ? vert[ face->v4].co : NULL; do { float dist; if(data->sphere_radius == 0.0f) dist = ray_tri_intersection(ray, hit->dist, t0, t1, t2); else dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2); if(dist >= 0 && dist < hit->dist) { hit->index = index; hit->dist = dist; VECADDFAC(hit->co, ray->origin, ray->direction, dist); normal_tri_v3( hit->no,t0, t1, t2); } t1 = t2; t2 = t3; t3 = NULL; } while(t2); }
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Base *base = NULL; DupliObject *dob; DerivedMesh *dm; Mesh *me= par->data; MTFace *mtface; MFace *mface; MVert *mvert; float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; int lay, oblay, totface, a; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; EditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; Mat4CpyMat4(pmat, par->obmat); em = BKE_mesh_get_editmesh(me); if(em) { int totvert; dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); dm->copyFaceArray(dm, mface); totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); BKE_mesh_end_editmesh(me, em); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); mvert= dm->getVertArray(dm); } if(G.rendering) { orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, orco, me->totvert, 0); mtface= me->mtface; } else { orco= NULL; mtface= NULL; } /* having to loop on scene OR group objects is NOT FUN */ if (GS(id->name) == ID_SCE) { sce = (Scene *)id; lay= sce->lay; base= sce->base.first; } else { group = (Group *)id; lay= group->layer; go = group->gobject.first; } /* Start looping on Scene OR Group objects */ while (base || go) { if (sce) { ob_iter= base->object; oblay = base->lay; } else { ob_iter= go->ob; oblay = ob_iter->lay; } if (lay & oblay && scene->obedit!=ob_iter) { ob=ob_iter->parent; while(ob) { if(ob==par) { ob = ob_iter; /* End Scene/Group object loop, below is generic */ /* par_space_mat - only used for groups so we can modify the space dupli's are in when par_space_mat is NULL ob->obmat can be used instead of ob__obmat */ if(par_space_mat) Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat); else Mat4CpyMat4(ob__obmat, ob->obmat); Mat3CpyMat4(imat, ob->parentinv); /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for(a=0; a<totface; a++) { int mv1 = mface[a].v1; int mv2 = mface[a].v2; int mv3 = mface[a].v3; int mv4 = mface[a].v4; float *v1= mvert[mv1].co; float *v2= mvert[mv2].co; float *v3= mvert[mv3].co; float *v4= (mv4)? mvert[mv4].co: NULL; float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; /* translation */ if(v4) CalcCent4f(cent, v1, v2, v3, v4); else CalcCent3f(cent, v1, v2, v3); Mat4MulVecfl(pmat, cent); VecSubf(cent, cent, pmat[3]); VecAddf(cent, cent, ob__obmat[3]); Mat4CpyMat4(obmat, ob__obmat); VECCOPY(obmat[3], cent); /* rotation */ triatoquat(v1, v2, v3, quat); QuatToMat3(quat, mat); /* scale */ if(par->transflag & OB_DUPLIFACES_SCALE) { float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3); size= sqrt(size) * par->dupfacesca; Mat3MulFloat(mat[0], size); } Mat3CpyMat3(mat3, mat); Mat3MulMat3(mat, imat, mat3); Mat4CpyMat4(tmat, obmat); Mat4MulMat43(obmat, tmat, mat); dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated); if(G.rendering) { w= (mv4)? 0.25f: 1.0f/3.0f; if(orco) { VECADDFAC(dob->orco, dob->orco, orco[mv1], w); VECADDFAC(dob->orco, dob->orco, orco[mv2], w); VECADDFAC(dob->orco, dob->orco, orco[mv3], w); if(mv4) VECADDFAC(dob->orco, dob->orco, orco[mv4], w); } if(mtface) { dob->uv[0] += w*mtface[a].uv[0][0]; dob->uv[1] += w*mtface[a].uv[0][1]; dob->uv[0] += w*mtface[a].uv[1][0]; dob->uv[1] += w*mtface[a].uv[1][1]; dob->uv[0] += w*mtface[a].uv[2][0]; dob->uv[1] += w*mtface[a].uv[2][1]; if(mv4) { dob->uv[0] += w*mtface[a].uv[3][0]; dob->uv[1] += w*mtface[a].uv[3][1]; } } } if(ob->transflag & OB_DUPLI) { float tmpmat[4][4]; Mat4CpyMat4(tmpmat, ob->obmat); Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */ object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(ob->obmat, tmpmat); } } break; } ob= ob->parent; } } if (sce) base= base->next; /* scene loop */ else go= go->next; /* group loop */ } if(par->mode & OB_MODE_EDIT) { MEM_freeN(mface); MEM_freeN(mvert); } if(orco) MEM_freeN(orco); dm->release(dm); }
static void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) { PartDeflect *pd = eff->pd; RNG *rng = pd->rng; float force[3]={0,0,0}; float temp[3]; float fac; float strength = pd->f_strength; float damp = pd->f_damp; float noise_factor = pd->f_noise; if(noise_factor > 0.0f) { strength += wind_func(rng, noise_factor); if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)) damp += wind_func(rng, noise_factor); } copy_v3_v3(force, efd->vec_to_point); switch(pd->forcefield){ case PFIELD_WIND: copy_v3_v3(force, efd->nor); mul_v3_fl(force, strength * efd->falloff); break; case PFIELD_FORCE: normalize_v3(force); mul_v3_fl(force, strength * efd->falloff); break; case PFIELD_VORTEX: /* old vortex force */ if(pd->shape == PFIELD_SHAPE_POINT) { cross_v3_v3v3(force, efd->nor, efd->vec_to_point); normalize_v3(force); mul_v3_fl(force, strength * efd->distance * efd->falloff); } else { /* new vortex force */ cross_v3_v3v3(temp, efd->nor2, efd->vec_to_point2); mul_v3_fl(temp, strength * efd->falloff); cross_v3_v3v3(force, efd->nor2, temp); mul_v3_fl(force, strength * efd->falloff); VECADDFAC(temp, temp, point->vel, -point->vel_to_sec); add_v3_v3(force, temp); } break; case PFIELD_MAGNET: if(eff->pd->shape == PFIELD_SHAPE_POINT) /* magnetic field of a moving charge */ cross_v3_v3v3(temp, efd->nor, efd->vec_to_point); else copy_v3_v3(temp, efd->nor); normalize_v3(temp); mul_v3_fl(temp, strength * efd->falloff); cross_v3_v3v3(force, point->vel, temp); mul_v3_fl(force, point->vel_to_sec); break; case PFIELD_HARMONIC: mul_v3_fl(force, -strength * efd->falloff); copy_v3_v3(temp, point->vel); mul_v3_fl(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec); add_v3_v3(force, temp); break; case PFIELD_CHARGE: mul_v3_fl(force, point->charge * strength * efd->falloff); break; case PFIELD_LENNARDJ: fac = pow((efd->size + point->size) / efd->distance, 6.0); fac = - fac * (1.0f - fac) / efd->distance; /* limit the repulsive term drastically to avoid huge forces */ fac = ((fac>2.0f) ? 2.0f : fac); mul_v3_fl(force, strength * fac); break; case PFIELD_BOID: /* Boid field is handled completely in boids code. */ return; case PFIELD_TURBULENCE: if(pd->flag & PFIELD_GLOBAL_CO) { copy_v3_v3(temp, point->loc); } else { VECADD(temp, efd->vec_to_point2, efd->nor2); } force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2,0,2); force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2,0,2); force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2,0,2); mul_v3_fl(force, strength * efd->falloff); break; case PFIELD_DRAG: copy_v3_v3(force, point->vel); fac = normalize_v3(force) * point->vel_to_sec; strength = MIN2(strength, 2.0f); damp = MIN2(damp, 2.0f); mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp)); break; } if(pd->flag & PFIELD_DO_LOCATION) { VECADDFAC(total_force, total_force, force, 1.0f/point->vel_to_sec); if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) { VECADDFAC(total_force, total_force, point->vel, -pd->f_flow * efd->falloff); } } if(pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) { float xvec[3] = {1.0f, 0.0f, 0.0f}; float dave[3]; mul_qt_v3(point->rot, xvec); cross_v3_v3v3(dave, xvec, force); if(pd->f_flow != 0.0f) { VECADDFAC(dave, dave, point->ave, -pd->f_flow * efd->falloff); } add_v3_v3(point->ave, dave); } }
static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) { TexResult result[4]; float tex_co[3], strength, force[3]; float nabla = eff->pd->tex_nabla; int hasrgb; short mode = eff->pd->tex_mode; if(!eff->pd->tex) return; result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; strength= eff->pd->f_strength * efd->falloff; copy_v3_v3(tex_co,point->loc); if(eff->pd->flag & PFIELD_TEX_2D) { float fac=-dot_v3v3(tex_co, efd->nor); VECADDFAC(tex_co, tex_co, efd->nor, fac); } if(eff->pd->flag & PFIELD_TEX_OBJECT) { mul_m4_v3(eff->ob->imat, tex_co); } hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 0, result); if(hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; force[1] = (0.5f - result->tg) * strength; force[2] = (0.5f - result->tb) * strength; } else { strength/=nabla; tex_co[0] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1); tex_co[0] -= nabla; tex_co[1] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2); tex_co[1] -= nabla; tex_co[2] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3); if(mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we dont have rgb fall back to grad */ force[0] = (result[0].tin - result[1].tin) * strength; force[1] = (result[0].tin - result[2].tin) * strength; force[2] = (result[0].tin - result[3].tin) * strength; } else { /*PFIELD_TEX_CURL*/ float dbdy, dgdz, drdz, dbdx, dgdx, drdy; dbdy = result[2].tb - result[0].tb; dgdz = result[3].tg - result[0].tg; drdz = result[3].tr - result[0].tr; dbdx = result[1].tb - result[0].tb; dgdx = result[1].tg - result[0].tg; drdy = result[2].tr - result[0].tr; force[0] = (dbdy - dgdz) * strength; force[1] = (drdz - dbdx) * strength; force[2] = (dgdx - drdy) * strength; } } if(eff->pd->flag & PFIELD_TEX_2D){ float fac = -dot_v3v3(force, efd->nor); VECADDFAC(force, force, efd->nor, fac); } add_v3_v3(total_force, force); }
/* BME_bevel_split_edge() is the main math work-house; its responsibilities are: * using the vert and the loop passed, get or make the split vert, set its coordinates * and transform properties, and set the max limits. * Finally, return the split vert. */ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, BME_Loop *l, float *up_vec, float value, BME_TransData_Head *td) { BME_TransData *vtd, *vtd1, *vtd2; BME_Vert *sv, *v2, *v3, *ov; BME_Loop *lv1, *lv2; BME_Edge *ne, *e1, *e2; float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3]; int is_edge, forward, is_split_vert; if (l == NULL) { /* what you call operator overloading in C :) * I wanted to use the same function for both wire edges and poly loops * so... here we walk around edges to find the needed verts */ forward = 1; is_split_vert = 0; if (v->edge == NULL) { //printf("We can't split a loose vert's edge!\n"); return NULL; } e1 = v->edge; /* we just use the first two edges */ e2 = BME_disk_nextedge(v->edge, v); if (e1 == e2) { //printf("You need at least two edges to use BME_bevel_split_edge()\n"); return NULL; } v2 = BME_edge_getothervert(e1, v); v3 = BME_edge_getothervert(e2, v); if (v1 != v2 && v1 != v3) { //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n"); return NULL; } if (v1 == v2) { v2 = v3; } else { e1 = e2; } ov = BME_edge_getothervert(e1,v); sv = BME_split_edge(bm,v,e1,&ne,0); //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ sv->tflag1 |= BME_BEVEL_BEVEL; ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ BME_bevel_get_vec(vec1,v1,v,td); BME_bevel_get_vec(vec2,v2,v,td); cross_v3_v3v3(t_up_vec,vec1,vec2); normalize_v3(t_up_vec); up_vec = t_up_vec; } else { /* establish loop direction */ if (l->v == v) { forward = 1; lv1 = l->next; lv2 = l->prev; v1 = l->next->v; v2 = l->prev->v; } else if (l->next->v == v) { forward = 0; lv1 = l; lv2 = l->next->next; v1 = l->v; v2 = l->next->next->v; } else { //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n"); return NULL; } if (BME_bevel_is_split_vert(lv1)) { is_split_vert = 1; sv = v1; if (forward) v1 = l->next->next->v; else v1 = l->prev->v; } else { is_split_vert = 0; ov = BME_edge_getothervert(l->e,v); sv = BME_split_edge(bm,v,l->e,&ne,0); //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ sv->tflag1 |= BME_BEVEL_BEVEL; ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ } if (BME_bevel_is_split_vert(lv2)) { if (forward) v2 = lv2->prev->v; else v2 = lv2->next->v; } } is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */ BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */ len = len_v3(vec1); normalize_v3(vec1); vtd = BME_get_transdata(td, sv); vtd1 = BME_get_transdata(td, v); vtd2 = BME_get_transdata(td,v1); if (vtd1->loc == NULL) { /* this is a vert with data only for calculating initial weights */ if (vtd1->weight < 0) { vtd1->weight = 0; } scale = vtd1->weight/vtd1->factor; if (!vtd1->max) { vtd1->max = BME_new_transdata_float(td); *vtd1->max = -1; } } else { scale = vtd1->weight; } vtd->max = vtd1->max; if (is_edge && vtd1->loc != NULL) { maxfactor = vtd1->maxfactor; } else { maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td); if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) { maxfactor = vtd->maxfactor; } } dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2; if (is_edge || dis > maxfactor*value) { dis = maxfactor*value; } VECADDFAC(sv->co,v->co,vec1,dis); VECSUB(vec1,sv->co,vtd1->org); dis = len_v3(vec1); normalize_v3(vec1); BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max); return sv; }