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; }
/* -------- pdDoEffectors() -------- generic force/speed system, now used for particles and softbodies scene = scene where it runs in, for time and stuff lb = listbase with objects that take part in effecting opco = global coord, as input force = force accumulator speed = actual current speed which can be altered cur_time = "external" time in frames, is constant for static particles loc_time = "local" time in frames, range <0-1> for the lifetime of particle par_layer = layer the caller is in flags = only used for softbody wind now guide = old speed of particle */ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) { /* Modifies the force on a particle according to its relation with the effector object Different kind of effectors include: Forcefields: Gravity-like attractor (force power is related to the inverse of distance to the power of a falloff value) Vortex fields: swirling effectors (particles rotate around Z-axis of the object. otherwise, same relation as) (Forcefields, but this is not done through a force/acceleration) Guide: particles on a path (particles are guided along a curve bezier or old nurbs) (is independent of other effectors) */ EffectorCache *eff; EffectorData efd; int p=0, tot = 1, step = 1; /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */ /* Check for min distance here? (yes would be cool to add that, ton) */ if(effectors) for(eff = effectors->first; eff; eff=eff->next) { /* object effectors were fully checked to be OK to evaluate! */ get_effector_tot(eff, &efd, point, &tot, &p, &step); for(; p<tot; p+=step) { if(get_effector_data(eff, &efd, point, 0)) { efd.falloff= effector_falloff(eff, &efd, point, weights); if(efd.falloff > 0.0f) efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point); if(efd.falloff <= 0.0f) ; /* don't do anything */ else if(eff->pd->forcefield == PFIELD_TEXTURE) do_texture_effector(eff, &efd, point, force); else { float temp1[3]={0,0,0}, temp2[3]; copy_v3_v3(temp1, force); do_physical_effector(eff, &efd, point, force); // for softbody backward compatibility if(point->flag & PE_WIND_AS_SPEED && impulse){ VECSUB(temp2, force, temp1); VECSUB(impulse, impulse, temp2); } } } else if(eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) { /* special case for harmonic effector */ VECADD(impulse, impulse, efd.vel); } } } }
static void compute_radiance(ScatterTree *tree, float *co, float *rad) { ScatterResult result; float rdsum[3], backrad[3], backrdsum[3]; memset(&result, 0, sizeof(result)); traverse_octree(tree, tree->root, co, 1, &result); /* the original paper doesn't do this, but we normalize over the sampled area and multiply with the reflectance. this is because our point samples are incomplete, there are no samples on parts of the mesh not visible from the camera. this can not only make it darker, but also lead to ugly color shifts */ VecMulf(result.rad, tree->ss[0]->frontweight); VecMulf(result.backrad, tree->ss[0]->backweight); VECCOPY(rad, result.rad); VECADD(backrad, result.rad, result.backrad); VECCOPY(rdsum, result.rdsum); VECADD(backrdsum, result.rdsum, result.backrdsum); if(rdsum[0] > 1e-16f) rad[0]= tree->ss[0]->color*rad[0]/rdsum[0]; if(rdsum[1] > 1e-16f) rad[1]= tree->ss[1]->color*rad[1]/rdsum[1]; if(rdsum[2] > 1e-16f) rad[2]= tree->ss[2]->color*rad[2]/rdsum[2]; if(backrdsum[0] > 1e-16f) backrad[0]= tree->ss[0]->color*backrad[0]/backrdsum[0]; if(backrdsum[1] > 1e-16f) backrad[1]= tree->ss[1]->color*backrad[1]/backrdsum[1]; if(backrdsum[2] > 1e-16f) backrad[2]= tree->ss[2]->color*backrad[2]/backrdsum[2]; rad[0]= MAX2(rad[0], backrad[0]); rad[1]= MAX2(rad[1], backrad[1]); rad[2]= MAX2(rad[2], backrad[2]); }
static DerivedMesh * applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { DerivedMesh *dm = derivedData, *result; ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; ParticleSimulationData sim; ParticleSystem *psys= NULL; ParticleData *pa= NULL, *pars= NULL; MFace *mface, *orig_mface; MVert *mvert, *orig_mvert; int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0; short track=ob->trackflag%3, trackneg, axis = pimd->axis; float max_co=0.0, min_co=0.0, temp_co[3], cross[3]; float *size=NULL; trackneg=((ob->trackflag>2)?1:0); if(pimd->ob==ob){ pimd->ob= NULL; return derivedData; } if(pimd->ob){ psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1); if(psys==NULL || psys->totpart==0) return derivedData; } else return derivedData; if(pimd->flag & eParticleInstanceFlag_Parents) totpart+=psys->totpart; if(pimd->flag & eParticleInstanceFlag_Children){ if(totpart==0) first_particle=psys->totpart; totpart+=psys->totchild; } if(totpart==0) return derivedData; sim.scene = md->scene; sim.ob = pimd->ob; sim.psys = psys; sim.psmd = psys_get_modifier(pimd->ob, psys); if(pimd->flag & eParticleInstanceFlag_UseSize) { int p; float *si; si = size = MEM_callocN(totpart * sizeof(float), "particle size array"); if(pimd->flag & eParticleInstanceFlag_Parents) { for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++) *si = pa->size; } if(pimd->flag & eParticleInstanceFlag_Children) { ChildParticle *cpa = psys->child; for(p=0; p<psys->totchild; p++, cpa++, si++) { *si = psys_get_child_size(psys, cpa, 0.0f, NULL); } } } pars=psys->particles; totvert=dm->getNumVerts(dm); totface=dm->getNumFaces(dm); maxvert=totvert*totpart; maxface=totface*totpart; psys->lattice=psys_get_lattice(&sim); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){ float min_r[3], max_r[3]; INIT_MINMAX(min_r, max_r); dm->getMinMax(dm, min_r, max_r); min_co=min_r[track]; max_co=max_r[track]; } result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface); mvert=result->getVertArray(result); orig_mvert=dm->getVertArray(dm); for(i=0; i<maxvert; i++){ MVert *inMV; MVert *mv = mvert + i; ParticleKey state; inMV = orig_mvert + i%totvert; DM_copy_vert_data(dm, result, i%totvert, i, 1); *mv = *inMV; /*change orientation based on object trackflag*/ copy_v3_v3(temp_co, mv->co); mv->co[axis]=temp_co[track]; mv->co[(axis+1)%3]=temp_co[(track+1)%3]; mv->co[(axis+2)%3]=temp_co[(track+2)%3]; if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){ float ran = 0.0f; if(pimd->random_position != 0.0f) { BLI_srandom(psys->seed + (i/totvert)%totpart); ran = pimd->random_position * BLI_frand(); } if(pimd->flag & eParticleInstanceFlag_KeepShape) { state.time = pimd->position * (1.0f - ran); } else { state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran); if(trackneg) state.time=1.0f-state.time; mv->co[axis] = 0.0; } psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1); normalize_v3(state.vel); /* TODO: incremental rotations somehow */ if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) { state.rot[0] = 1; state.rot[1] = state.rot[2] = state.rot[3] = 0.0f; } else { float temp[3] = {0.0f,0.0f,0.0f}; temp[axis] = 1.0f; cross_v3_v3v3(cross, temp, state.vel); /* state.vel[axis] is the only component surviving from a dot product with the axis */ axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis])); } } else{ state.time=-1.0; psys_get_particle_state(&sim, first_particle + i/totvert, &state,1); } mul_qt_v3(state.rot,mv->co); if(pimd->flag & eParticleInstanceFlag_UseSize) mul_v3_fl(mv->co, size[i/totvert]); VECADD(mv->co,mv->co,state.co); } mface=result->getFaceArray(result); orig_mface=dm->getFaceArray(dm); for(i=0; i<maxface; i++){ MFace *inMF; MFace *mf = mface + i; if(pimd->flag & eParticleInstanceFlag_Parents){ if(i/totface>=psys->totpart){ if(psys->part->childtype==PART_CHILD_PARTICLES) pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent; else pa= NULL; } else pa=pars+i/totface; } else{ if(psys->part->childtype==PART_CHILD_PARTICLES) pa=psys->particles+(psys->child+i/totface)->parent; else pa= NULL; } if(pa){ if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue; if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue; if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue; } inMF = orig_mface + i%totface; DM_copy_face_data(dm, result, i%totface, i, 1); *mf = *inMF; mf->v1+=(i/totface)*totvert; mf->v2+=(i/totface)*totvert; mf->v3+=(i/totface)*totvert; if(mf->v4) mf->v4+=(i/totface)*totvert; } CDDM_calc_edges(result); CDDM_calc_normals(result); if(psys->lattice){ end_latt_deform(psys->lattice); psys->lattice= NULL; } if(size) MEM_freeN(size); return result; }
/* The computational routine */ void gradOrder1ScaleC(double *dy, double *yt, double *rhot, int L, int R, int dim, int CSP, int CSD, double *scales2, double *scaleweight2, double energyweight) { /* dy already initialized to zeros */ int CSPL = CSP*L; int CSDL = 1; double invR = 1.0/R; int i, l, sl, si; if (dim == 2) { #pragma omp parallel for schedule(static) shared(dy,yt,rhot,L,R,dim,CSP,CSD,CSPL,CSDL,scales2,scaleweight2) private(i,l,sl,si) for (i=0; i<L; i++) { /* particle */ double xi[2] = {rhot[INDRHOX(i,0)],rhot[INDRHOX(i,1)]}; double dxi[2] = {yt[INDYX(i,0,0,0,0)],yt[INDYX(i,1,0,0,0)]}; for (l=0; l<L; l++) { /* particle */ double xl[2] = {rhot[INDRHOX(l,0)],rhot[INDRHOX(l,1)]}; double dxl[2] = {yt[INDYX(l,0,0,0,0)],yt[INDYX(l,1,0,0,0)]}; double ximxl[2]; VECMINUS(ximxl,xi,xl); double v = VECDOT2(ximxl,ximxl); for (sl=0; sl<R; sl++) { /* scale */ double alsl[2] = {rhot[INDRHOP(l,0,sl)],rhot[INDRHOP(l,1,sl)]}; double aisl[2] = {rhot[INDRHOP(i,0,sl)],rhot[INDRHOP(i,1,sl)]}; double rsl2 = scales2[sl]; double swsl2 = scaleweight2[sl]; double kbasesl = exp(-v/rsl2); double d1ksl = D1Ks(kbasesl,rsl2,swsl2); double d1kslXximxl[2]; VECSCALAR(d1kslXximxl,d1ksl,ximxl); double dalsl[2] = {yt[INDYP(l,0,sl,0,0,0)],yt[INDYP(l,1,sl,0,0,0)]}; /* dx */ double rt1; VECDOT(rt1,aisl,dxl); double rt2; VECDOT(rt2,alsl,dxi); double vt1[2]; VECSCALAR(vt1,2*(rt1+rt2),d1kslXximxl); dy[INDYX(i,0,0,0,0)] += vt1[0]; dy[INDYX(i,1,0,0,0)] += vt1[1]; for (si=0; si<R; si++) { /* scale */ double alsi[2] = {rhot[INDRHOP(l,0,si)],rhot[INDRHOP(l,1,si)]}; double aisi[2] = {rhot[INDRHOP(i,0,si)],rhot[INDRHOP(i,1,si)]}; double daisi[2] = {yt[INDYP(i,0,si,0,0,0)],yt[INDYP(i,1,si,0,0,0)]}; double daisl[2] = {yt[INDYP(i,0,sl,0,0,0)],yt[INDYP(i,1,sl,0,0,0)]}; double rsi2 = scales2[si]; double swsi2 = scaleweight2[si]; double kbasesi = exp(-v/rsi2); double ksi = Ks(kbasesi,swsi2); double d1ksi = D1Ks(kbasesi,rsi2,swsi2); double d2ksi = D2Ks(kbasesi,rsi2,swsi2); double aislTXalsi; VECDOT(aislTXalsi,aisl,alsi); double aisiTXalsl; VECDOT(aisiTXalsl,aisi,alsl); /* dx */ VECSCALAR(vt1,aislTXalsi,daisl); double vt2[2]; VECSCALAR(vt2,aisiTXalsl,dalsl); double vt3[2]; VECMINUS(vt3,vt1,vt2); double rt; VECDOT(rt,ximxl,vt3); VECSCALAR(vt1,-2*d1ksi,vt3); VECSCALAR(vt2,-4*d2ksi*rt,ximxl); VECADD(vt3,vt1,vt2); dy[INDYX(i,0,0,0,0)] += vt3[0]; dy[INDYX(i,1,0,0,0)] += vt3[1]; /* da */ VECSCALAR(vt1,d1ksl,daisi); VECSCALAR(vt2,d1ksi,dalsl); VECMINUS(vt3,vt1,vt2); VECDOT(rt,ximxl,vt3); VECSCALAR(vt1,-2*rt,alsl); VECSCALAR(vt2,invR*ksi,dxl); VECADD(vt3,vt1,vt2); dy[INDYP(i,0,si,0,0,0)] += vt3[0]; dy[INDYP(i,1,si,0,0,0)] += vt3[1]; } } } } } else { /* #pragma omp parallel for schedule(static) shared(dy,yt,rhot,L,R,dim,CSP,CSD,CSPL,CSDL,scales2,scaleweight2) private(i,l,sl,si)*/ for (i=0; i<L; i++) { /* particle */ double xi[3] = {rhot[INDRHOX(i,0)],rhot[INDRHOX(i,1)],rhot[INDRHOX(i,2)]}; double dxi[3] = {yt[INDYX(i,0,0,0,0)],yt[INDYX(i,1,0,0,0)],yt[INDYX(i,2,0,0,0)]}; for (l=0; l<L; l++) { /* particle */ double xl[3] = {rhot[INDRHOX(l,0)],rhot[INDRHOX(l,1)],rhot[INDRHOX(l,2)]}; double dxl[3] = {yt[INDYX(l,0,0,0,0)],yt[INDYX(l,1,0,0,0)],yt[INDYX(l,2,0,0,0)]}; double ximxl[3]; _3VECMINUS(ximxl,xi,xl); double v = _3VECDOT2(ximxl,ximxl); for (sl=0; sl<R; sl++) { /* scale */ double alsl[3] = {rhot[INDRHOP(l,0,sl)],rhot[INDRHOP(l,1,sl)],rhot[INDRHOP(l,2,sl)]}; double aisl[3] = {rhot[INDRHOP(i,0,sl)],rhot[INDRHOP(i,1,sl)],rhot[INDRHOP(i,2,sl)]}; double rsl2 = scales2[sl]; double swsl2 = scaleweight2[sl]; double kbasesl = exp(-v/rsl2); double d1ksl = D1Ks(kbasesl,rsl2,swsl2); double d1kslXximxl[3]; _3VECSCALAR(d1kslXximxl,d1ksl,ximxl); double dalsl[3] = {yt[INDYP(l,0,sl,0,0,0)],yt[INDYP(l,1,sl,0,0,0)],yt[INDYP(l,2,sl,0,0,0)]}; /* dx */ double rt1; _3VECDOT(rt1,aisl,dxl); double rt2; _3VECDOT(rt2,alsl,dxi); double vt1[3]; _3VECSCALAR(vt1,2*(rt1+rt2),d1kslXximxl); dy[INDYX(i,0,0,0,0)] += vt1[0]; dy[INDYX(i,1,0,0,0)] += vt1[1]; dy[INDYX(i,2,0,0,0)] += vt1[2]; for (si=0; si<R; si++) { /* scale */ double alsi[3] = {rhot[INDRHOP(l,0,si)],rhot[INDRHOP(l,1,si)],rhot[INDRHOP(l,2,si)]}; double aisi[3] = {rhot[INDRHOP(i,0,si)],rhot[INDRHOP(i,1,si)],rhot[INDRHOP(i,2,si)]}; double daisi[3] = {yt[INDYP(i,0,si,0,0,0)],yt[INDYP(i,1,si,0,0,0)],yt[INDYP(i,2,si,0,0,0)]}; double daisl[3] = {yt[INDYP(i,0,sl,0,0,0)],yt[INDYP(i,1,sl,0,0,0)],yt[INDYP(i,2,sl,0,0,0)]}; double rsi2 = scales2[si]; double swsi2 = scaleweight2[si]; double kbasesi = exp(-v/rsi2); double ksi = Ks(kbasesi,swsi2); double d1ksi = D1Ks(kbasesi,rsi2,swsi2); double d2ksi = D2Ks(kbasesi,rsi2,swsi2); double aislTXalsi; _3VECDOT(aislTXalsi,aisl,alsi); double aisiTXalsl; _3VECDOT(aisiTXalsl,aisi,alsl); /* dx */ _3VECSCALAR(vt1,aislTXalsi,daisl); double vt2[3]; _3VECSCALAR(vt2,aisiTXalsl,dalsl); double vt3[3]; _3VECMINUS(vt3,vt1,vt2); double rt; _3VECDOT(rt,ximxl,vt3); _3VECSCALAR(vt1,-2*d1ksi,vt3); _3VECSCALAR(vt2,-4*d2ksi*rt,ximxl); _3VECADD(vt3,vt1,vt2); dy[INDYX(i,0,0,0,0)] += vt3[0]; dy[INDYX(i,1,0,0,0)] += vt3[1]; dy[INDYX(i,2,0,0,0)] += vt3[2]; /* da */ _3VECSCALAR(vt1,d1ksl,daisi); _3VECSCALAR(vt2,d1ksi,dalsl); _3VECMINUS(vt3,vt1,vt2); _3VECDOT(rt,ximxl,vt3); _3VECSCALAR(vt1,-2*rt,alsl); _3VECSCALAR(vt2,invR*ksi,dxl); _3VECADD(vt3,vt1,vt2); dy[INDYP(i,0,si,0,0,0)] += vt3[0]; dy[INDYP(i,1,si,0,0,0)] += vt3[1]; dy[INDYP(i,2,si,0,0,0)] += vt3[2]; } } } } } addEgradt(dy,yt,rhot,L,R,dim,CSP,CSD,scales2,scaleweight2,energyweight); }
int Fbonded_eval_impr_term(Fbonded *p, const ImprPrm *prm, const dvec *pos_i, const dvec *pos_j, const dvec *pos_k, const dvec *pos_l, dvec *f_i, dvec *f_j, dvec *f_k, dvec *f_l, dreal *u, dreal virial[NELEMS_VIRIAL]) { dvec r12, r23, r34; dvec A, B, C; dreal rA, rB, rC; dreal cos_phi, sin_phi, phi; dreal K, K1; dvec f1, f2, f3; dreal k = prm->k_impr; dreal delta = prm->psi0; dreal diff; Domain_shortest_vec(p->domain, &r12, pos_i, pos_j); Domain_shortest_vec(p->domain, &r23, pos_j, pos_k); Domain_shortest_vec(p->domain, &r34, pos_k, pos_l); VECCROSS(A, r12, r23); VECCROSS(B, r23, r34); VECCROSS(C, r23, A); rA = 1 / sqrt(VECLEN2(A)); rB = 1 / sqrt(VECLEN2(B)); rC = 1 / sqrt(VECLEN2(C)); VECMUL(B, rB, B); /* normalize B */ cos_phi = VECDOT(A, B) * rA; sin_phi = VECDOT(C, B) * rC; phi = -atan2(sin_phi, cos_phi); diff = phi - delta; if (diff < -M_PI) diff += 2.0 * M_PI; else if (diff > M_PI) diff -= 2.0 * M_PI; K = k * diff * diff; K1 = 2.0 * k * diff; if (fabs(sin_phi) > 0.1) { dvec dcosdA, dcosdB; dvec tv1, tv2; /* use sine version to avoid 1/cos terms */ VECMUL(A, rA, A); /* normalize A */ VECMSUB(dcosdA, cos_phi, A, B); VECMUL(dcosdA, rA, dcosdA); VECMSUB(dcosdB, cos_phi, B, A); VECMUL(dcosdB, rB, dcosdB); K1 /= sin_phi; VECCROSS(f1, r23, dcosdA); VECMUL(f1, K1, f1); VECCROSS(f3, dcosdB, r23); VECMUL(f3, K1, f3); VECCROSS(tv1, dcosdA, r12); VECCROSS(tv2, r34, dcosdB); VECADD(f2, tv1, tv2); VECMUL(f2, K1, f2); } else { dvec dsindB, dsindC; /* phi is too close to 0 or pi, use cos version to avoid 1/sin */ VECMUL(C, rC, C); /* normalize C */ VECMSUB(dsindC, sin_phi, C, B); VECMUL(dsindC, rC, dsindC); VECMSUB(dsindB, sin_phi, B, C); VECMUL(dsindB, rB, dsindB); K1 /= -cos_phi; f1.x = K1 * ((r23.y * r23.y + r23.z * r23.z) * dsindC.x - r23.x * r23.y * dsindC.y - r23.x * r23.z * dsindC.z); f1.y = K1 * ((r23.z * r23.z + r23.x * r23.x) * dsindC.y - r23.y * r23.z * dsindC.z - r23.y * r23.x * dsindC.x); f1.z = K1 * ((r23.x * r23.x + r23.y * r23.y) * dsindC.z - r23.z * r23.x * dsindC.x - r23.z * r23.y * dsindC.y); VECCROSS(f3, dsindB, r23); VECMUL(f3, K1, f3); f2.x = K1 * (-(r23.y * r12.y + r23.z * r12.z) * dsindC.x + (2.0 * r23.x * r12.y - r12.x * r23.y) * dsindC.y + (2.0 * r23.x * r12.z - r12.x * r23.z) * dsindC.z + dsindB.z * r34.y - dsindB.y * r34.z); f2.y = K1 * (-(r23.z * r12.z + r23.x * r12.x) * dsindC.y + (2.0 * r23.y * r12.z - r12.y * r23.z) * dsindC.z + (2.0 * r23.y * r12.x - r12.y * r23.x) * dsindC.x + dsindB.x * r34.z - dsindB.z * r34.x); f2.z = K1 * (-(r23.x * r12.x + r23.y * r12.y) * dsindC.z + (2.0 * r23.z * r12.x - r12.z * r23.x) * dsindC.x + (2.0 * r23.z * r12.y - r12.z * r23.y) * dsindC.y + dsindB.y * r34.x - dsindB.x * r34.y); } *u += K; VECADD(*f_i, *f_i, f1); f_j->x += f2.x - f1.x; f_j->y += f2.y - f1.y; f_j->z += f2.z - f1.z; f_k->x += f3.x - f2.x; f_k->y += f3.y - f2.y; f_k->z += f3.z - f2.z; VECSUB(*f_l, *f_l, f3); virial[VIRIAL_XX] += (f1.x * r12.x + f2.x * r23.x + f3.x * r34.x); virial[VIRIAL_XY] += (f1.x * r12.y + f2.x * r23.y + f3.x * r34.y); virial[VIRIAL_XZ] += (f1.x * r12.z + f2.x * r23.z + f3.x * r34.z); virial[VIRIAL_YY] += (f1.y * r12.y + f2.y * r23.y + f3.y * r34.y); virial[VIRIAL_YZ] += (f1.y * r12.z + f2.y * r23.z + f3.y * r34.z); virial[VIRIAL_ZZ] += (f1.z * r12.z + f2.z * r23.z + f3.z * r34.z); return OK; }
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; ParticleDupliWeight *dw; ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int lay, a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; if(psys==0) return; /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; part=psys->part; if(part==0) return; if(!psys_check_enabled(par, psys)) return; ctime = bsystem_time(scene, par, (float)scene->r.cfra, 0.0); totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); lay= scene->lay; if((psys->renderdata || part->draw_as==PART_DRAW_REND) && ((part->ren_as == PART_DRAW_OB && part->dup_ob) || (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) { psys_check_group_weights(part); /* if we have a hair particle system, use the path cache */ if(part->type == PART_HAIR) { if(psys->flag & PSYS_HAIR_DONE) hair= (totchild == 0 || psys->childcache) && psys->pathcache; if(!hair) return; /* we use cache, update totchild according to cached data */ totchild = psys->totchildcache; totpart = psys->totcached; } psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if(part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); if(part->draw & PART_DRAW_COUNT_GR) { for(dw=part->dupliweights.first; dw; dw=dw->next) totgroup += dw->count; } else { for(go=part->dup_group->gobject.first; go; go=go->next) totgroup++; } /* we also copy the actual objects to restore afterwards, since * where_is_object_time will change the object which breaks transform */ oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); if(part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for(a=0; a<totgroup; dw=dw->next) { for(b=0; b<dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { go = part->dup_group->gobject.first; for(a=0; a<totgroup; a++, go=go->next) { oblist[a] = go->ob; obcopylist[a] = *go->ob; } } } else { ob = part->dup_ob; obcopy = *ob; } if(totchild==0 || part->draw & PART_DRAW_PARENT) a = 0; else a = totpart; for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if(a<totpart) { /* handle parent particle */ if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; pa_num = pa->num; pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; pa_num = a; pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, 0); } if(part->ren_as==PART_DRAW_GR) { /* for groups, pick the object based on settings */ if(part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; else if(part->from==PART_FROM_PARTICLE) b= pa_num % totgroup; else b= a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; oldobmat = obcopylist[b].obmat; } else { obmat= ob->obmat; oldobmat= obcopy.obmat; } if(hair) { /* hair we handle separate and compute transform based on hair keys */ if(a < totpart) { cache = psys->pathcache[a]; psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); pamat[3][3]= 1.0f; } else { /* first key */ state.time = ctime; if(psys_get_particle_state(&sim, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); VECCOPY(pamat[3], state.co); pamat[3][3]= 1.0f; } if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { Mat4MulMat4(tmat, oblist[b]->obmat, pamat); Mat4MulFloat3((float *)tmat, size*scale); if(par_space_mat) Mat4MulMat4(mat, tmat, par_space_mat); else Mat4CpyMat4(mat, tmat); dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, obcopylist[b].obmat); if(G.rendering) psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); VECCOPY(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; Mat4CpyMat4(mat, pamat); Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size*scale); if(part->draw & PART_DRAW_GLOBAL_OB) VECADD(tmat[3], tmat[3], vec); if(par_space_mat) Mat4MulMat4(mat, tmat, par_space_mat); else Mat4CpyMat4(mat, tmat); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, oldobmat); if(G.rendering) psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } /* restore objects since they were changed in where_is_object_time */ if(part->ren_as==PART_DRAW_GR) { for(a=0; a<totgroup; a++) *(oblist[a])= obcopylist[a]; } else *ob= obcopy; } /* clean up */ if(oblist) MEM_freeN(oblist); if(obcopylist) MEM_freeN(obcopylist); if(psys->lattice) { end_latt_deform(psys->lattice); psys->lattice = NULL; } }
/* makes Mesh out of editmesh */ void load_editMesh(Scene *scene, Object *obedit) { Mesh *me= obedit->data; MVert *mvert, *oldverts; MEdge *medge; MFace *mface; MSelect *mselect; EditMesh *em= me->edit_mesh; EditVert *eve; EditFace *efa, *efa_act; EditEdge *eed; EditSelection *ese; float *fp, *newkey, *oldkey; int i, a, ototvert; /* this one also tests of edges are not in faces: */ /* eed->f2==0: not in face, f2==1: draw it */ /* eed->f1 : flag for dynaface (cylindertest, old engine) */ /* eve->f1 : flag for dynaface (sphere test, old engine) */ /* eve->f2 : being used in vertexnormals */ edge_drawflags(me, em); EM_stats_update(em); /* new Vertex block */ if(em->totvert==0) mvert= NULL; else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); /* new Edge block */ if(em->totedge==0) medge= NULL; else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); /* new Face block */ if(em->totface==0) mface= NULL; else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); /* lets save the old verts just in case we are actually working on * a key ... we now do processing of the keys at the end */ oldverts= me->mvert; ototvert= me->totvert; /* don't free this yet */ CustomData_set_layer(&me->vdata, CD_MVERT, NULL); /* free custom data */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); /* add new custom data */ me->totvert= em->totvert; me->totedge= em->totedge; me->totface= em->totface; CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); mesh_update_customdata_pointers(me); /* the vertices, use ->tmp.l as counter */ eve= em->verts.first; a= 0; while(eve) { VECCOPY(mvert->co, eve->co); /* vertex normal */ normal_float_to_short_v3(mvert->no, eve->no); /* note: it used to remove me->dvert when it was not in use, cancelled that... annoying when you have a fresh vgroup */ CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); eve->tmp.l = a++; /* counter */ mvert->flag= 0; mvert->flag |= (eve->f & SELECT); if (eve->h) mvert->flag |= ME_HIDE; mvert->bweight= (char)(255.0f*eve->bweight); eve= eve->next; mvert++; } /* the edges */ a= 0; eed= em->edges.first; while(eed) { medge->v1= (unsigned int) eed->v1->tmp.l; medge->v2= (unsigned int) eed->v2->tmp.l; medge->flag= (eed->f & SELECT) | ME_EDGERENDER; if(eed->f2<2) medge->flag |= ME_EDGEDRAW; if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; if(eed->sharp) medge->flag |= ME_SHARP; if(eed->seam) medge->flag |= ME_SEAM; if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes if(eed->h & 1) medge->flag |= ME_HIDE; medge->crease= (char)(255.0f*eed->crease); medge->bweight= (char)(255.0f*eed->bweight); CustomData_from_em_block(&em->edata, &me->edata, eed->data, a); eed->tmp.l = a++; medge++; eed= eed->next; } /* the faces */ a = 0; efa= em->faces.first; efa_act= EM_get_actFace(em, 0); i = 0; me->act_face = -1; while(efa) { mface= &((MFace *) me->mface)[i]; mface->v1= (unsigned int) efa->v1->tmp.l; mface->v2= (unsigned int) efa->v2->tmp.l; mface->v3= (unsigned int) efa->v3->tmp.l; if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; mface->mat_nr= efa->mat_nr; mface->flag= efa->flag; /* bit 0 of flag is already taken for smooth... */ if(efa->h) { mface->flag |= ME_HIDE; mface->flag &= ~ME_FACE_SEL; } else { if(efa->f & 1) mface->flag |= ME_FACE_SEL; else mface->flag &= ~ME_FACE_SEL; } /* watch: efa->e1->f2==0 means loose edge */ if(efa->e1->f2==1) { efa->e1->f2= 2; } if(efa->e2->f2==1) { efa->e2->f2= 2; } if(efa->e3->f2==1) { efa->e3->f2= 2; } if(efa->e4 && efa->e4->f2==1) { efa->e4->f2= 2; } CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); /* no index '0' at location 3 or 4 */ test_index_face(mface, &me->fdata, i, efa->v4?4:3); if (efa_act == efa) me->act_face = a; efa->tmp.l = a++; i++; efa= efa->next; } /* patch hook indices and vertex parents */ { Object *ob; ModifierData *md; EditVert **vertMap = NULL; int j; for (ob=G.main->object.first; ob; ob=ob->id.next) { if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) { /* duplicate code from below, make it function later...? */ if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } if(ob->par1 < ototvert) { eve = vertMap[ob->par1]; if(eve) ob->par1= eve->tmp.l; } if(ob->par2 < ototvert) { eve = vertMap[ob->par2]; if(eve) ob->par2= eve->tmp.l; } if(ob->par3 < ototvert) { eve = vertMap[ob->par3]; if(eve) ob->par3= eve->tmp.l; } } if (ob->data==me) { for (md=ob->modifiers.first; md; md=md->next) { if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } for (i=j=0; i<hmd->totindex; i++) { if(hmd->indexar[i] < ototvert) { eve = vertMap[hmd->indexar[i]]; if (eve) { hmd->indexar[j++] = eve->tmp.l; } } else j++; } hmd->totindex = j; } } } } if (vertMap) MEM_freeN(vertMap); } /* are there keys? */ if(me->key) { KeyBlock *currkey; KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); float (*ofs)[3] = NULL; /* editing the base key should update others */ if(me->key->type==KEY_RELATIVE && oldverts) { int act_is_basis = 0; /* find if this key is a basis for any others */ for(currkey = me->key->block.first; currkey; currkey= currkey->next) { if(em->shapenr-1 == currkey->relative) { act_is_basis = 1; break; } } if(act_is_basis) { /* active key is a base */ float (*fp)[3]= actkey->data; i=0; ofs= MEM_callocN(sizeof(float) * 3 * em->totvert, "currkey->data"); eve= em->verts.first; mvert = me->mvert; while(eve) { if(eve->keyindex>=0) { sub_v3_v3v3(ofs[i], mvert->co, fp[eve->keyindex]); } eve= eve->next; i++; mvert++; } } } /* Lets reorder the key data so that things line up roughly * with the way things were before editmode */ currkey = me->key->block.first; while(currkey) { int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative)); fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data"); oldkey = currkey->data; eve= em->verts.first; i = 0; mvert = me->mvert; while(eve) { if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex if(currkey == actkey) { if(actkey == me->key->refkey) { VECCOPY(fp, mvert->co); } else { VECCOPY(fp, mvert->co); if(oldverts) { VECCOPY(mvert->co, oldverts[eve->keyindex].co); } } } else { if(oldkey) { VECCOPY(fp, oldkey + 3 * eve->keyindex); } } } else { VECCOPY(fp, mvert->co); } /* propagate edited basis offsets to other shapes */ if(apply_offset) { VECADD(fp, fp, ofs[i]); } fp+= 3; ++i; ++mvert; eve= eve->next; } currkey->totelem= em->totvert; if(currkey->data) MEM_freeN(currkey->data); currkey->data = newkey; currkey= currkey->next; } if(ofs) MEM_freeN(ofs); } if(oldverts) MEM_freeN(oldverts); i = 0; for(ese=em->selected.first; ese; ese=ese->next) i++; me->totselect = i; if(i==0) mselect= NULL; else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); if(me->mselect) MEM_freeN(me->mselect); me->mselect= mselect; for(ese=em->selected.first; ese; ese=ese->next){ mselect->type = ese->type; if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; mselect++; } /* to be sure: clear ->tmp.l pointers */ eve= em->verts.first; while(eve) { eve->tmp.l = 0; eve= eve->next; } eed= em->edges.first; while(eed) { eed->tmp.l = 0; eed= eed->next; } efa= em->faces.first; while(efa) { efa->tmp.l = 0; efa= efa->next; } /* remake softbody of all users */ if(me->id.us>1) { Base *base; for(base= scene->base.first; base; base= base->next) if(base->object->data==me) base->object->recalc |= OB_RECALC_DATA; } mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); /* topology could be changed, ensure mdisps are ok */ multires_topology_changed(scene, obedit); }
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 fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) { MVert *mvert = dm->getVertArray(dm); MFace *mface = dm->getFaceArray(dm); int i = 0, divs = 0; int *tridivs = NULL; float cell_len = 1.0 / 50.0; // for res = 50 int newdivs = 0; int quads = 0, facecounter = 0; // count quads for(i = 0; i < dm->getNumFaces(dm); i++) { if(mface[i].v4) quads++; } calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len); // count triangle divisions for(i = 0; i < dm->getNumFaces(dm) + quads; i++) { divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1); } // printf("divs: %d\n", divs); scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints"); for(i = 0; i < dm->getNumVerts(dm); i++) { float tmpvec[3]; VECCOPY(tmpvec, mvert[i].co); Mat4MulVecfl (ob->obmat, tmpvec); VECCOPY(&scs->points[i * 3], tmpvec); } for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++) { int again = 0; do { int j, k; int divs1 = tridivs[3 * facecounter + 0]; int divs2 = tridivs[3 * facecounter + 1]; //int divs3 = tridivs[3 * facecounter + 2]; float side1[3], side2[3], trinormorg[3], trinorm[3]; if(again == 1 && mface[i].v4) { VECSUB(side1, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co); VECSUB(side2, mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co); } else { VECSUB(side1, mvert[ mface[i].v2 ].co, mvert[ mface[i].v1 ].co); VECSUB(side2, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co); } Crossf(trinormorg, side1, side2); Normalize(trinormorg); VECCOPY(trinorm, trinormorg); VecMulf(trinorm, 0.25 * cell_len); for(j = 0; j <= divs1; j++) { for(k = 0; k <= divs2; k++) { float p1[3], p2[3], p3[3], p[3]={0,0,0}; const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0); const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0); float tmpvec[3]; if(uf+vf > 1.0) { // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2); continue; } VECCOPY(p1, mvert[ mface[i].v1 ].co); if(again == 1 && mface[i].v4) { VECCOPY(p2, mvert[ mface[i].v3 ].co); VECCOPY(p3, mvert[ mface[i].v4 ].co); } else { VECCOPY(p2, mvert[ mface[i].v2 ].co); VECCOPY(p3, mvert[ mface[i].v3 ].co); } VecMulf(p1, (1.0-uf-vf)); VecMulf(p2, uf); VecMulf(p3, vf); VECADD(p, p1, p2); VECADD(p, p, p3); if(newdivs > divs) printf("mem problem\n"); // mMovPoints.push_back(p + trinorm); VECCOPY(tmpvec, p); VECADD(tmpvec, tmpvec, trinorm); Mat4MulVecfl (ob->obmat, tmpvec); VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec); newdivs++; if(newdivs > divs) printf("mem problem\n"); // mMovPoints.push_back(p - trinorm); VECCOPY(tmpvec, p); VECSUB(tmpvec, tmpvec, trinorm); Mat4MulVecfl (ob->obmat, tmpvec); VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec); newdivs++; } } if(again == 0 && mface[i].v4) again++; else again = 0; facecounter++; } while(again!=0); } scs->numpoints = dm->getNumVerts(dm) + newdivs; MEM_freeN(tridivs); }
static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); ParticleData *pa; PTCacheEdit *edit; PTCacheEditPoint *point; PTCacheEditKey *ekey = NULL; HairKey *key; BVHTreeFromMesh bvhtree= {NULL}; BVHTreeNearest nearest; MFace *mface; DerivedMesh *dm = NULL; int numverts; int i, k; float hairmat[4][4], imat[4][4]; float v[4][3], vec[3]; if(!psys || !psys->part || psys->part->type != PART_HAIR) return; edit= psys->edit; point= edit ? edit->points : NULL; if(psmd->dm->deformedOnly) /* we don't want to mess up psmd->dm when converting to global coordinates below */ dm= CDDM_copy(psmd->dm); else dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); numverts = dm->getNumVerts (dm); /* convert to global coordinates */ for (i=0; i<numverts; i++) mul_m4_v3(ob->obmat, CDDM_get_vert(dm, i)->co); bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6); for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) { key = pa->hair; nearest.index = -1; nearest.dist = FLT_MAX; BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree); if(nearest.index == -1) { if (G.f & G_DEBUG) printf("No nearest point found for hair root!"); continue; } mface = CDDM_get_face(dm,nearest.index); copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co); copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co); copy_v3_v3(v[2], CDDM_get_vert(dm,mface->v3)->co); if(mface->v4) { copy_v3_v3(v[3], CDDM_get_vert(dm,mface->v4)->co); interp_weights_poly_v3( pa->fuv,v, 4, nearest.co); } else interp_weights_poly_v3( pa->fuv,v, 3, nearest.co); pa->num = nearest.index; pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL); psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); invert_m4_m4(imat,hairmat); VECSUB(vec, nearest.co, key->co); if(point) { ekey = point->keys; point++; } for(k=0,key=pa->hair; k<pa->totkey; k++,key++) { VECADD(key->co, key->co, vec); mul_m4_v3(imat,key->co); if(ekey) { ekey->flag |= PEK_USE_WCO; ekey++; } } } free_bvhtree_from_mesh(&bvhtree); dm->release(dm); psys_free_path_cache(psys, psys->edit); psys->flag &= ~PSYS_GLOBAL_HAIR; PE_update_object(scene, ob, 0); }
void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow) { RegionView3D *rv3d= ar->regiondata; float viewnormal[3]; int i, j, n, good_index; float d, d0, dd, ds; float *points = NULL; int numpoints = 0; float cor[3] = {1.,1.,1.}; int gl_depth = 0, gl_blend = 0; /* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */ float cv[][3] = { {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} }; // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] float edges[12][2][3] = { {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} }; /* Fragment program to calculate the view3d of smoke */ /* using 2 textures, density and shadow */ const char *text = "!!ARBfp1.0\n" "PARAM dx = program.local[0];\n" "PARAM darkness = program.local[1];\n" "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" "TEMP temp, shadow, value;\n" "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" "MUL value, temp, darkness;\n" "MUL value, value, dx;\n" "MUL value, value, f;\n" "EX2 temp, -value.r;\n" "SUB temp.a, 1.0, temp.r;\n" "MUL temp.r, temp.r, shadow.r;\n" "MUL temp.g, temp.g, shadow.r;\n" "MUL temp.b, temp.b, shadow.r;\n" "MOV result.color, temp;\n" "END\n"; GLuint prog; float size[3]; if(!tex) { printf("Could not allocate 3D texture for 3D View smoke drawing.\n"); return; } tstart(); VECSUB(size, max, min); // maxx, maxy, maxz cv[0][0] = max[0]; cv[0][1] = max[1]; cv[0][2] = max[2]; // minx, maxy, maxz cv[1][0] = min[0]; cv[1][1] = max[1]; cv[1][2] = max[2]; // minx, miny, maxz cv[2][0] = min[0]; cv[2][1] = min[1]; cv[2][2] = max[2]; // maxx, miny, maxz cv[3][0] = max[0]; cv[3][1] = min[1]; cv[3][2] = max[2]; // maxx, maxy, minz cv[4][0] = max[0]; cv[4][1] = max[1]; cv[4][2] = min[2]; // minx, maxy, minz cv[5][0] = min[0]; cv[5][1] = max[1]; cv[5][2] = min[2]; // minx, miny, minz cv[6][0] = min[0]; cv[6][1] = min[1]; cv[6][2] = min[2]; // maxx, miny, minz cv[7][0] = max[0]; cv[7][1] = min[1]; cv[7][2] = min[2]; VECCOPY(edges[0][0], cv[4]); // maxx, maxy, minz VECCOPY(edges[1][0], cv[5]); // minx, maxy, minz VECCOPY(edges[2][0], cv[6]); // minx, miny, minz VECCOPY(edges[3][0], cv[7]); // maxx, miny, minz VECCOPY(edges[4][0], cv[3]); // maxx, miny, maxz VECCOPY(edges[5][0], cv[2]); // minx, miny, maxz VECCOPY(edges[6][0], cv[6]); // minx, miny, minz VECCOPY(edges[7][0], cv[7]); // maxx, miny, minz VECCOPY(edges[8][0], cv[1]); // minx, maxy, maxz VECCOPY(edges[9][0], cv[2]); // minx, miny, maxz VECCOPY(edges[10][0], cv[6]); // minx, miny, minz VECCOPY(edges[11][0], cv[5]); // minx, maxy, minz // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]); // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]); edges[0][1][2] = size[2]; edges[1][1][2] = size[2]; edges[2][1][2] = size[2]; edges[3][1][2] = size[2]; edges[4][1][1] = size[1]; edges[5][1][1] = size[1]; edges[6][1][1] = size[1]; edges[7][1][1] = size[1]; edges[8][1][0] = size[0]; edges[9][1][0] = size[0]; edges[10][1][0] = size[0]; edges[11][1][0] = size[0]; glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); glLoadMatrixf(rv3d->viewmat); // glMultMatrixf(ob->obmat); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* printf("Viewinv:\n"); printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]); printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]); printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]); */ // get view vector VECCOPY(viewnormal, rv3d->viewinv[2]); normalize_v3(viewnormal); // find cube vertex that is closest to the viewer for (i=0; i<8; i++) { float x,y,z; x = cv[i][0] - viewnormal[0]; y = cv[i][1] - viewnormal[1]; z = cv[i][2] - viewnormal[2]; if ((x>=min[0])&&(x<=max[0]) &&(y>=min[1])&&(y<=max[1]) &&(z>=min[2])&&(z<=max[2])) { break; } } if(i >= 8) { /* fallback, avoid using buffer over-run */ i= 0; } // printf("i: %d\n", i); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { glEnable(GL_FRAGMENT_PROGRAM_ARB); glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); // cell spacing glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); // custom parameter for smoke style (higher = thicker) glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); GPU_texture_bind(tex, 0); if(tex_shadow) GPU_texture_bind(tex_shadow, 1); else printf("No volume shadow\n"); if (!GPU_non_power_of_two_support()) { cor[0] = (float)res[0]/(float)larger_pow2(res[0]); cor[1] = (float)res[1]/(float)larger_pow2(res[1]); cor[2] = (float)res[2]/(float)larger_pow2(res[2]); } // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 // (a,b,c), the plane normal, are given by viewdir // d is the parameter along the view direction. the first d is given by // inserting previously found vertex into the plane equation d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]); dd = 0.05; // ds/512.0f; n = 0; good_index = i; // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds); points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview"); while(1) { float p0[3]; float tmp_point[3], tmp_point2[3]; if(dd*(float)n > ds) break; VECCOPY(tmp_point, viewnormal); mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n)); VECADD(tmp_point2, cv[good_index], tmp_point); d = INPR(tmp_point2, viewnormal); // printf("my d: %f\n", d); // intersect_edges returns the intersection points of all cube edges with // the given plane that lie within the cube numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges); // printf("points: %d\n", numpoints); if (numpoints > 2) { VECCOPY(p0, points); // sort points to get a convex polygon for(i = 1; i < numpoints - 1; i++) { for(j = i + 1; j < numpoints; j++) { if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) { float tmp2[3]; VECCOPY(tmp2, &points[j * 3]); VECCOPY(&points[j * 3], &points[i * 3]); VECCOPY(&points[i * 3], tmp2); } } } // printf("numpoints: %d\n", numpoints); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i * 3 + 0] - min[0] )*cor[0]/size[0], (points[i * 3 + 1] - min[1])*cor[1]/size[1], (points[i * 3 + 2] - min[2])*cor[2]/size[2]); glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); } glEnd(); } n++; } tend(); // printf ( "Draw Time: %f\n",( float ) tval() ); if(tex_shadow) GPU_texture_unbind(tex_shadow); GPU_texture_unbind(tex); if(GLEW_ARB_fragment_program) { glDisable(GL_FRAGMENT_PROGRAM_ARB); glDeleteProgramsARB(1, &prog); } MEM_freeN(points); if(!gl_blend) glDisable(GL_BLEND); if(gl_depth) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); } }
/* * Function adapted from David Eberly's distance tools (LGPL) * http://www.geometrictools.com/LibFoundation/Distance/Distance.html */ static float nearest_point_in_tri_surface(const float *v0,const float *v1,const float *v2,const float *p, int *v, int *e, float *nearest ) { float diff[3]; float e0[3]; float e1[3]; float A00; float A01; float A11; float B0; float B1; float C; float Det; float S; float T; float sqrDist; int lv = -1, le = -1; VECSUB(diff, v0, p); VECSUB(e0, v1, v0); VECSUB(e1, v2, v0); A00 = INPR ( e0, e0 ); A01 = INPR( e0, e1 ); A11 = INPR ( e1, e1 ); B0 = INPR( diff, e0 ); B1 = INPR( diff, e1 ); C = INPR( diff, diff ); Det = fabs( A00 * A11 - A01 * A01 ); S = A01 * B1 - A11 * B0; T = A01 * B0 - A00 * B1; if ( S + T <= Det ) { if ( S < 0.0f ) { if ( T < 0.0f ) // Region 4 { if ( B0 < 0.0f ) { T = 0.0f; if ( -B0 >= A00 ) { S = (float)1.0; sqrDist = A00 + 2.0f * B0 + C; lv = 1; } else { if(fabsf(A00) > FLT_EPSILON) S = -B0/A00; else S = 0.0f; sqrDist = B0 * S + C; le = 0; } } else { S = 0.0f; if ( B1 >= 0.0f ) { T = 0.0f; sqrDist = C; lv = 0; } else if ( -B1 >= A11 ) { T = 1.0f; sqrDist = A11 + 2.0f * B1 + C; lv = 2; } else { if(fabsf(A11) > FLT_EPSILON) T = -B1 / A11; else T = 0.0f; sqrDist = B1 * T + C; le = 1; } } } else // Region 3 { S = 0.0f; if ( B1 >= 0.0f ) { T = 0.0f; sqrDist = C; lv = 0; } else if ( -B1 >= A11 ) { T = 1.0f; sqrDist = A11 + 2.0f * B1 + C; lv = 2; } else { if(fabsf(A11) > FLT_EPSILON) T = -B1 / A11; else T = 0.0; sqrDist = B1 * T + C; le = 1; } } } else if ( T < 0.0f ) // Region 5 { T = 0.0f; if ( B0 >= 0.0f ) { S = 0.0f; sqrDist = C; lv = 0; } else if ( -B0 >= A00 ) { S = 1.0f; sqrDist = A00 + 2.0f * B0 + C; lv = 1; } else { if(fabsf(A00) > FLT_EPSILON) S = -B0 / A00; else S = 0.0f; sqrDist = B0 * S + C; le = 0; } } else // Region 0 { // Minimum at interior lv float invDet; if(fabsf(Det) > FLT_EPSILON) invDet = 1.0f / Det; else invDet = 0.0f; S *= invDet; T *= invDet; sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0) + T * ( A01 * S + A11 * T + 2.0f * B1 ) + C; } } else { float tmp0, tmp1, numer, denom; if ( S < 0.0f ) // Region 2 { tmp0 = A01 + B0; tmp1 = A11 + B1; if ( tmp1 > tmp0 ) { numer = tmp1 - tmp0; denom = A00 - 2.0f * A01 + A11; if ( numer >= denom ) { S = 1.0f; T = 0.0f; sqrDist = A00 + 2.0f * B0 + C; lv = 1; } else { if(fabsf(denom) > FLT_EPSILON) S = numer / denom; else S = 0.0f; T = 1.0f - S; sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) + T * ( A01 * S + A11 * T + 2.0f * B1 ) + C; le = 2; } } else { S = 0.0f; if ( tmp1 <= 0.0f ) { T = 1.0f; sqrDist = A11 + 2.0f * B1 + C; lv = 2; } else if ( B1 >= 0.0f ) { T = 0.0f; sqrDist = C; lv = 0; } else { if(fabsf(A11) > FLT_EPSILON) T = -B1 / A11; else T = 0.0f; sqrDist = B1 * T + C; le = 1; } } } else if ( T < 0.0f ) // Region 6 { tmp0 = A01 + B1; tmp1 = A00 + B0; if ( tmp1 > tmp0 ) { numer = tmp1 - tmp0; denom = A00 - 2.0f * A01 + A11; if ( numer >= denom ) { T = 1.0f; S = 0.0f; sqrDist = A11 + 2.0f * B1 + C; lv = 2; } else { if(fabsf(denom) > FLT_EPSILON) T = numer / denom; else T = 0.0f; S = 1.0f - T; sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) + T * ( A01 * S + A11 * T + 2.0f * B1 ) + C; le = 2; } } else { T = 0.0f; if ( tmp1 <= 0.0f ) { S = 1.0f; sqrDist = A00 + 2.0f * B0 + C; lv = 1; } else if ( B0 >= 0.0f ) { S = 0.0f; sqrDist = C; lv = 0; } else { if(fabsf(A00) > FLT_EPSILON) S = -B0 / A00; else S = 0.0f; sqrDist = B0 * S + C; le = 0; } } } else // Region 1 { numer = A11 + B1 - A01 - B0; if ( numer <= 0.0f ) { S = 0.0f; T = 1.0f; sqrDist = A11 + 2.0f * B1 + C; lv = 2; } else { denom = A00 - 2.0f * A01 + A11; if ( numer >= denom ) { S = 1.0f; T = 0.0f; sqrDist = A00 + 2.0f * B0 + C; lv = 1; } else { if(fabsf(denom) > FLT_EPSILON) S = numer / denom; else S = 0.0f; T = 1.0f - S; sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) + T * ( A01 * S + A11 * T + 2.0f * B1 ) + C; le = 2; } } } } // Account for numerical round-off error if ( sqrDist < FLT_EPSILON ) sqrDist = 0.0f; { float w[3], x[3], y[3], z[3]; VECCOPY(w, v0); VECCOPY(x, e0); mul_v3_fl(x, S); VECCOPY(y, e1); mul_v3_fl(y, T); VECADD(z, w, x); VECADD(z, z, y); //VECSUB(d, p, z); VECCOPY(nearest, z); // d = p - ( v0 + S * e0 + T * e1 ); } *v = lv; *e = le; return sqrDist; }
/** * BME_bevel_poly * * Polygon inset tool: * * Insets a polygon/face based on the tflag1's of its vertices * and edges. Used by the bevel tool only, for now. * The parameter "value" is the distance to inset (should be negative). * The parameter "options" is not currently used. * * Returns - * A BME_Poly pointer to the resulting inner face. */ static BME_Poly *BME_bevel_poly(BME_Mesh *bm, BME_Poly *f, float value, int options, BME_TransData_Head *td) { BME_Loop *l, *ol; BME_TransData *vtd1, *vtd2; float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1; int len, i; up_vec[0] = 0.0f; up_vec[1] = 0.0f; up_vec[2] = 0.0f; /* find a good normal for this face (there's better ways, I'm sure) */ ol = f->loopbase; l = ol->next; for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) { BME_bevel_get_vec(vec1,l->next->v,ol->v,td); BME_bevel_get_vec(vec2,l->v,ol->v,td); cross_v3_v3v3(vec3,vec2,vec1); VECADD(up_vec,up_vec,vec3); i++; } mul_v3_fl(up_vec,1.0f/i); normalize_v3(up_vec); for (i=0,len=f->len; i<len; i++,l=l->next) { if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) { max = 1.0f; l = BME_bevel_edge(bm, l, value, options, up_vec, td); } else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) { max = 1.0f; l = BME_bevel_vert(bm, l, value, options, up_vec, td); } } /* max pass */ if (value > 0.5 && max > 0) { max = -1; for (i=0,len=f->len; i<len; i++,l=l->next) { if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) { BME_bevel_get_vec(vec1,l->v,l->next->v,td); vtd1 = BME_get_transdata(td,l->v); vtd2 = BME_get_transdata(td,l->next->v); if (vtd1->loc == NULL) { fac1 = 0; } else { VECCOPY(vec2,vtd1->vec); mul_v3_fl(vec2,vtd1->factor); if (dot_v3v3(vec1, vec1)) { project_v3_v3v3(vec2,vec2,vec1); fac1 = len_v3(vec2)/value; } else { fac1 = 0; } } if (vtd2->loc == NULL) { fac2 = 0; } else { VECCOPY(vec3,vtd2->vec); mul_v3_fl(vec3,vtd2->factor); if (dot_v3v3(vec1, vec1)) { project_v3_v3v3(vec2,vec3,vec1); fac2 = len_v3(vec2)/value; } else { fac2 = 0; } } if (fac1 || fac2) { max = len_v3(vec1)/(fac1 + fac2); if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) { *vtd1->max = max; } if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) { *vtd2->max = max; } } } } } return l->f; }