Exemplo n.º 1
4
Arquivo: smoke.c Projeto: jinjoh/NOOR
/*! init triangle divisions */
void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len) 
{
	// mTriangleDivs1.resize( faces.size() );
	// mTriangleDivs2.resize( faces.size() );
	// mTriangleDivs3.resize( faces.size() );

	size_t i = 0, facecounter = 0;
	float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
	float maxpart = ABS(maxscale[0]);
	float scaleFac = 0;
	float fsTri = 0;
	if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
	if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
	scaleFac = 1.0 / maxpart;
	// featureSize = mLevel[mMaxRefine].nodeSize
	fsTri = cell_len * 0.5 * scaleFac;

	if(*tridivs)
		MEM_freeN(*tridivs);

	*tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");

	for(i = 0, facecounter = 0; i < numfaces; i++) 
	{
		float p0[3], p1[3], p2[3];
		float side1[3];
		float side2[3];
		float side3[3];
		int divs1=0, divs2=0, divs3=0;

		VECCOPY(p0, verts[faces[i].v1].co);
		Mat4MulVecfl (ob->obmat, p0);
		VECCOPY(p1, verts[faces[i].v2].co);
		Mat4MulVecfl (ob->obmat, p1);
		VECCOPY(p2, verts[faces[i].v3].co);
		Mat4MulVecfl (ob->obmat, p2);

		VECSUB(side1, p1, p0);
		VECSUB(side2, p2, p0);
		VECSUB(side3, p1, p2);

		if(INPR(side1, side1) > fsTri*fsTri) 
		{ 
			float tmp = Normalize(side1);
			divs1 = (int)ceil(tmp/fsTri); 
		}
		if(INPR(side2, side2) > fsTri*fsTri) 
		{ 
			float tmp = Normalize(side2);
			divs2 = (int)ceil(tmp/fsTri); 
			
			/*
			// debug
			if(i==0)
				printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
			*/
		}

		(*tridivs)[3 * facecounter + 0] = divs1;
		(*tridivs)[3 * facecounter + 1] = divs2;
		(*tridivs)[3 * facecounter + 2] = divs3;

		// TODO quad case
		if(faces[i].v4)
		{
			divs1=0, divs2=0, divs3=0;

			facecounter++;
			
			VECCOPY(p0, verts[faces[i].v3].co);
			Mat4MulVecfl (ob->obmat, p0);
			VECCOPY(p1, verts[faces[i].v4].co);
			Mat4MulVecfl (ob->obmat, p1);
			VECCOPY(p2, verts[faces[i].v1].co);
			Mat4MulVecfl (ob->obmat, p2);

			VECSUB(side1, p1, p0);
			VECSUB(side2, p2, p0);
			VECSUB(side3, p1, p2);

			if(INPR(side1, side1) > fsTri*fsTri) 
			{ 
				float tmp = Normalize(side1);
				divs1 = (int)ceil(tmp/fsTri); 
			}
			if(INPR(side2, side2) > fsTri*fsTri) 
			{ 
				float tmp = Normalize(side2);
				divs2 = (int)ceil(tmp/fsTri); 
			}

			(*tridivs)[3 * facecounter + 0] = divs1;
			(*tridivs)[3 * facecounter + 1] = divs2;
			(*tridivs)[3 * facecounter + 2] = divs3;
		}
		facecounter++;
	}
}
Exemplo n.º 2
0
/* only creates a table for a single channel in CurveMapping */
static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
{
	CurveMapPoint *cmp= cuma->curve;
	BezTriple *bezt;
	float *fp, *allpoints, *lastpoint, curf, range;
	int a, totpoint;
	
	if(cuma->curve==NULL) return;
	
	/* default rect also is table range */
	cuma->mintable= clipr->xmin;
	cuma->maxtable= clipr->xmax;
	
	/* hrmf... we now rely on blender ipo beziers, these are more advanced */
	bezt= MEM_callocN(cuma->totpoint*sizeof(BezTriple), "beztarr");
	
	for(a=0; a<cuma->totpoint; a++) {
		cuma->mintable= MIN2(cuma->mintable, cmp[a].x);
		cuma->maxtable= MAX2(cuma->maxtable, cmp[a].x);
		bezt[a].vec[1][0]= cmp[a].x;
		bezt[a].vec[1][1]= cmp[a].y;
		if(cmp[a].flag & CUMA_VECTOR)
			bezt[a].h1= bezt[a].h2= HD_VECT;
		else
			bezt[a].h1= bezt[a].h2= HD_AUTO;
	}
	
	for(a=0; a<cuma->totpoint; a++) {
		if(a==0)
			calchandle_curvemap(bezt, NULL, bezt+1, 0);
		else if(a==cuma->totpoint-1)
			calchandle_curvemap(bezt+a, bezt+a-1, NULL, 0);
		else
			calchandle_curvemap(bezt+a, bezt+a-1, bezt+a+1, 0);
	}
	
	/* first and last handle need correction, instead of pointing to center of next/prev, 
		we let it point to the closest handle */
	if(cuma->totpoint>2) {
		float hlen, nlen, vec[3];
		
		if(bezt[0].h2==HD_AUTO) {
			
			hlen= len_v3v3(bezt[0].vec[1], bezt[0].vec[2]);	/* original handle length */
			/* clip handle point */
			VECCOPY(vec, bezt[1].vec[0]);
			if(vec[0] < bezt[0].vec[1][0])
				vec[0]= bezt[0].vec[1][0];
			
			sub_v3_v3(vec, bezt[0].vec[1]);
			nlen= len_v3(vec);
			if(nlen>FLT_EPSILON) {
				mul_v3_fl(vec, hlen/nlen);
				add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
				sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
			}
		}
		a= cuma->totpoint-1;
		if(bezt[a].h2==HD_AUTO) {
			
			hlen= len_v3v3(bezt[a].vec[1], bezt[a].vec[0]);	/* original handle length */
			/* clip handle point */
			VECCOPY(vec, bezt[a-1].vec[2]);
			if(vec[0] > bezt[a].vec[1][0])
				vec[0]= bezt[a].vec[1][0];
			
			sub_v3_v3(vec, bezt[a].vec[1]);
			nlen= len_v3(vec);
			if(nlen>FLT_EPSILON) {
				mul_v3_fl(vec, hlen/nlen);
				add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
				sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
			}
		}
	}	
	/* make the bezier curve */
	if(cuma->table)
		MEM_freeN(cuma->table);
	totpoint= (cuma->totpoint-1)*CM_RESOL;
	fp= allpoints= MEM_callocN(totpoint*2*sizeof(float), "table");
	
	for(a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) {
		correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]);
		forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2*sizeof(float));	
		forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2*sizeof(float));
	}
	
	/* store first and last handle for extrapolation, unit length */
	cuma->ext_in[0]= bezt[0].vec[0][0] - bezt[0].vec[1][0];
	cuma->ext_in[1]= bezt[0].vec[0][1] - bezt[0].vec[1][1];
	range= sqrt(cuma->ext_in[0]*cuma->ext_in[0] + cuma->ext_in[1]*cuma->ext_in[1]);
	cuma->ext_in[0]/= range;
	cuma->ext_in[1]/= range;
	
	a= cuma->totpoint-1;
	cuma->ext_out[0]= bezt[a].vec[1][0] - bezt[a].vec[2][0];
	cuma->ext_out[1]= bezt[a].vec[1][1] - bezt[a].vec[2][1];
	range= sqrt(cuma->ext_out[0]*cuma->ext_out[0] + cuma->ext_out[1]*cuma->ext_out[1]);
	cuma->ext_out[0]/= range;
	cuma->ext_out[1]/= range;
	
	/* cleanup */
	MEM_freeN(bezt);

	range= CM_TABLEDIV*(cuma->maxtable - cuma->mintable);
	cuma->range= 1.0f/range;
	
	/* now make a table with CM_TABLE equal x distances */
	fp= allpoints;
	lastpoint= allpoints + 2*(totpoint-1);
	cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table");
	
	for(a=0; a<=CM_TABLE; a++) {
		curf= cuma->mintable + range*(float)a;
		cmp[a].x= curf;
		
		/* get the first x coordinate larger than curf */
		while(curf >= fp[0] && fp!=lastpoint) {
			fp+=2;
		}
		if(fp==allpoints || (curf >= fp[0] && fp==lastpoint))
			cmp[a].y= curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
		else {
			float fac1= fp[0] - fp[-2];
			float fac2= fp[0] - curf;
			if(fac1 > FLT_EPSILON)
				fac1= fac2/fac1;
			else
				fac1= 0.0f;
			cmp[a].y= fac1*fp[-1] + (1.0f-fac1)*fp[1];
		}
	}
	
	MEM_freeN(allpoints);
	cuma->table= cmp;
}
Exemplo n.º 3
0
/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
static PyObject *M_Geometry_tesselate_polygon(PyObject *UNUSED(self), PyObject *polyLineSeq)
{
	PyObject *tri_list; /*return this list of tri's */
	PyObject *polyLine, *polyVec;
	int i, len_polylines, len_polypoints, ls_error= 0;

	/* display listbase */
	ListBase dispbase={NULL, NULL};
	DispList *dl;
	float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
	int index, *dl_face, totpoints=0;

	if(!PySequence_Check(polyLineSeq)) {
		PyErr_SetString(PyExc_TypeError,
		                "expected a sequence of poly lines");
		return NULL;
	}

	len_polylines= PySequence_Size(polyLineSeq);

	for(i= 0; i < len_polylines; ++i) {
		polyLine= PySequence_GetItem(polyLineSeq, i);
		if (!PySequence_Check(polyLine)) {
			freedisplist(&dispbase);
			Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
			PyErr_SetString(PyExc_TypeError,
			                "One or more of the polylines is not a sequence of mathutils.Vector's");
			return NULL;
		}

		len_polypoints= PySequence_Size(polyLine);
		if (len_polypoints>0) { /* dont bother adding edges as polylines */
#if 0
			if (EXPP_check_sequence_consistency(polyLine, &vector_Type) != 1) {
				freedisplist(&dispbase);
				Py_DECREF(polyLine);
				PyErr_SetString(PyExc_TypeError,
				                "A point in one of the polylines is not a mathutils.Vector type");
				return NULL;
			}
#endif
			dl= MEM_callocN(sizeof(DispList), "poly disp");
			BLI_addtail(&dispbase, dl);
			dl->type= DL_INDEX3;
			dl->nr= len_polypoints;
			dl->type= DL_POLY;
			dl->parts= 1; /* no faces, 1 edge loop */
			dl->col= 0; /* no material */
			dl->verts= fp= MEM_callocN(sizeof(float)*3*len_polypoints, "dl verts");
			dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index");

			for(index= 0; index<len_polypoints; ++index, fp+=3) {
				polyVec= PySequence_GetItem(polyLine, index);
				if(VectorObject_Check(polyVec)) {

					if(BaseMath_ReadCallback((VectorObject *)polyVec) == -1)
						ls_error= 1;

					fp[0]= ((VectorObject *)polyVec)->vec[0];
					fp[1]= ((VectorObject *)polyVec)->vec[1];
					if(((VectorObject *)polyVec)->size > 2)
						fp[2]= ((VectorObject *)polyVec)->vec[2];
					else
						fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
				}
				else {
					ls_error= 1;
				}

				totpoints++;
				Py_DECREF(polyVec);
			}
		}
		Py_DECREF(polyLine);
	}

	if(ls_error) {
		freedisplist(&dispbase); /* possible some dl was allocated */
		PyErr_SetString(PyExc_TypeError,
		                "A point in one of the polylines "
		                "is not a mathutils.Vector type");
		return NULL;
	}
	else if (totpoints) {
		/* now make the list to return */
		filldisplist(&dispbase, &dispbase, 0);

		/* The faces are stored in a new DisplayList
		thats added to the head of the listbase */
		dl= dispbase.first;

		tri_list= PyList_New(dl->parts);
		if(!tri_list) {
			freedisplist(&dispbase);
			PyErr_SetString(PyExc_RuntimeError,
			                "failed to make a new list");
			return NULL;
		}

		index= 0;
		dl_face= dl->index;
		while(index < dl->parts) {
			PyList_SET_ITEM(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]));
			dl_face+= 3;
			index++;
		}
		freedisplist(&dispbase);
	}
	else {
		/* no points, do this so scripts dont barf */
		freedisplist(&dispbase); /* possible some dl was allocated */
		tri_list= PyList_New(0);
	}

	return tri_list;
}
Exemplo n.º 4
0
/* calculate a curve-deform path for a curve 
 *  - only called from displist.c -> do_makeDispListCurveTypes
 */
void calc_curvepath(Object *ob)
{
	BevList *bl;
	BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
	PathPoint *pp;
	Curve *cu;
	Nurb *nu;
	Path *path;
	float *fp, *dist, *maxdist, xyz[3];
	float fac, d = 0, fac1, fac2;
	int a, tot, cycl = 0;
	ListBase *nurbs;
	
	/* in a path vertices are with equal differences: path->len = number of verts */
	/* NOW WITH BEVELCURVE!!! */
	
	if (ob == NULL || ob->type != OB_CURVE) return;
	cu = ob->data;

	nurbs = BKE_curve_nurbs_get(cu);
	nu = nurbs->first;

	if (cu->path) free_path(cu->path);
	cu->path = NULL;
	
	bl = cu->bev.first;
	if (bl == NULL || !bl->nr) return;

	cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
	
	/* if POLY: last vertice != first vertice */
	cycl = (bl->poly != -1);
	
	if (cycl) tot = bl->nr;
	else tot = bl->nr - 1;
	
	path->len = tot + 1;
	/* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */
	if (path->len < nu->resolu * SEGMENTSU(nu)) path->len = nu->resolu * SEGMENTSU(nu);
	
	dist = (float *)MEM_mallocN((tot + 1) * 4, "calcpathdist");

	/* all lengths in *dist */
	bevp = bevpfirst = (BevPoint *)(bl + 1);
	fp = dist;
	*fp = 0;
	for (a = 0; a < tot; a++) {
		fp++;
		if (cycl && a == tot - 1)
			sub_v3_v3v3(xyz, bevpfirst->vec, bevp->vec);
		else
			sub_v3_v3v3(xyz, (bevp + 1)->vec, bevp->vec);
		
		*fp = *(fp - 1) + len_v3(xyz);
		bevp++;
	}
	
	path->totdist = *fp;
	
	/* the path verts  in path->data */
	/* now also with TILT value */
	pp = path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint) * path->len, "pathdata");

	bevp = bevpfirst;
	bevpn = bevp + 1;
	bevplast = bevpfirst + (bl->nr - 1);
	fp = dist + 1;
	maxdist = dist + tot;
	fac = 1.0f / ((float)path->len - 1.0f);
	fac = fac * path->totdist;
	
	for (a = 0; a < path->len; a++) {
		
		d = ((float)a) * fac;
		
		/* we're looking for location (distance) 'd' in the array */
		while ((d >= *fp) && fp < maxdist) {
			fp++;
			if (bevp < bevplast) bevp++;
			bevpn = bevp + 1;
			if (bevpn > bevplast) {
				if (cycl) bevpn = bevpfirst;
				else bevpn = bevplast;
			}
		}
		
		fac1 = *(fp) - *(fp - 1);
		fac2 = *(fp) - d;
		fac1 = fac2 / fac1;
		fac2 = 1.0f - fac1;
		
		interp_v3_v3v3(pp->vec, bevp->vec, bevpn->vec, fac2);
		pp->vec[3] = fac1 * bevp->alfa + fac2 * bevpn->alfa;
		pp->radius = fac1 * bevp->radius + fac2 * bevpn->radius;
		pp->weight = fac1 * bevp->weight + fac2 * bevpn->weight;
		interp_qt_qtqt(pp->quat, bevp->quat, bevpn->quat, fac2);
		normalize_qt(pp->quat);
		
		pp++;
	}
	
	MEM_freeN(dist);
}
Exemplo n.º 5
0
static int get_sequence_len(char *filename, int *ofs)
{
  int frame;
  int numdigit;

  if (!BLI_path_frame_get(filename, &frame, &numdigit)) {
    return 1;
  }

  char path[FILE_MAX];
  BLI_path_abs(filename, BKE_main_blendfile_path_from_global());
  BLI_split_dir_part(filename, path, FILE_MAX);

  if (path[0] == '\0') {
    /* The filename had no path, so just use the blend file path. */
    BLI_split_dir_part(BKE_main_blendfile_path_from_global(), path, FILE_MAX);
  }

  DIR *dir = opendir(path);
  if (dir == NULL) {
    fprintf(stderr,
            "Error opening directory '%s': %s\n",
            path,
            errno ? strerror(errno) : "unknown error");
    return -1;
  }

  const char *ext = ".abc";
  const char *basename = BLI_path_basename(filename);
  const int len = strlen(basename) - (numdigit + strlen(ext));

  ListBase frames;
  BLI_listbase_clear(&frames);

  struct dirent *fname;
  while ((fname = readdir(dir)) != NULL) {
    /* do we have the right extension? */
    if (!strstr(fname->d_name, ext)) {
      continue;
    }

    if (!STREQLEN(basename, fname->d_name, len)) {
      continue;
    }

    CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame");

    BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit);

    BLI_addtail(&frames, cache_frame);
  }

  closedir(dir);

  BLI_listbase_sort(&frames, cmp_frame);

  CacheFrame *cache_frame = frames.first;

  if (cache_frame) {
    int frame_curr = cache_frame->framenr;
    (*ofs) = frame_curr;

    while (cache_frame && (cache_frame->framenr == frame_curr)) {
      ++frame_curr;
      cache_frame = cache_frame->next;
    }

    BLI_freelistN(&frames);

    return frame_curr - (*ofs);
  }

  return 1;
}
Exemplo n.º 6
0
static void mesh_calc_edges_mdata(
        MVert *UNUSED(allvert), MFace *allface, MLoop *allloop,
        MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly,
        const bool use_old,
        MEdge **r_medge, int *r_totedge)
{
	MPoly *mpoly;
	MFace *mface;
	MEdge *medge, *med;
	EdgeHash *hash;
	struct EdgeSort *edsort, *ed;
	int a, totedge = 0;
	unsigned int totedge_final = 0;
	unsigned int edge_index;

	/* we put all edges in array, sort them, and detect doubles that way */

	for (a = totface, mface = allface; a > 0; a--, mface++) {
		if (mface->v4) totedge += 4;
		else if (mface->v3) totedge += 3;
		else totedge += 1;
	}

	if (totedge == 0) {
		/* flag that mesh has edges */
		(*r_medge) = MEM_callocN(0, __func__);
		(*r_totedge) = 0;
		return;
	}

	ed = edsort = MEM_mallocN(totedge * sizeof(struct EdgeSort), "EdgeSort");

	for (a = totface, mface = allface; a > 0; a--, mface++) {
		to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2);
		if (mface->v4) {
			to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
			to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4);
			to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1);
		}
		else if (mface->v3) {
			to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
			to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1);
		}
	}

	qsort(edsort, totedge, sizeof(struct EdgeSort), vergedgesort);

	/* count final amount */
	for (a = totedge, ed = edsort; a > 1; a--, ed++) {
		/* edge is unique when it differs from next edge, or is last */
		if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) totedge_final++;
	}
	totedge_final++;

	medge = MEM_callocN(sizeof(MEdge) * totedge_final, __func__);

	for (a = totedge, med = medge, ed = edsort; a > 1; a--, ed++) {
		/* edge is unique when it differs from next edge, or is last */
		if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) {
			med->v1 = ed->v1;
			med->v2 = ed->v2;
			if (use_old == false || ed->is_draw) med->flag = ME_EDGEDRAW | ME_EDGERENDER;
			if (ed->is_loose) med->flag |= ME_LOOSEEDGE;

			/* order is swapped so extruding this edge as a surface wont flip face normals
			 * with cyclic curves */
			if (ed->v1 + 1 != ed->v2) {
				SWAP(unsigned int, med->v1, med->v2);
			}
			med++;
		}
Exemplo n.º 7
0
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 = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
	DupliObject *dob;
	ParticleDupliWeight *dw;
	ParticleSettings *part;
	ParticleData *pa;
	ChildParticle *cpa = NULL;
	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 a, b, counter, hair = 0;
	int totpart, totchild, totgroup = 0 /*, pa_num */;

	int no_draw_flag = PARS_UNEXIST;

	if (psys == NULL) return;
	
	/* simple preventing of too deep nested groups */
	if (level > MAX_DUPLI_RECUR) return;
	
	part = psys->part;

	if (part == NULL)
		return;

	if (!psys_check_enabled(par, psys))
		return;

	if (G.rendering == 0)
		no_draw_flag |= PARS_NO_DISP;
	
	ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */

	totpart = psys->totpart;
	totchild = psys->totchild;

	BLI_srandom(31415926 + psys->seed);

	if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
		ParticleSimulationData sim = {NULL};
		sim.scene = scene;
		sim.ob = par;
		sim.psys = psys;
		sim.psmd = psys_get_modifier(par, psys);
		/* make sure emitter imat is in global coordinates instead of render view coordinates */
		invert_m4_m4(par->imat, par->obmat);

		/* first check for loops (particle system object used as dupli object) */
		if (part->ren_as == PART_DRAW_OB) {
			if (ELEM(part->dup_ob, NULL, par))
				return;
		}
		else { /*PART_DRAW_GR */
			if (part->dup_group == NULL || part->dup_group->gobject.first == NULL)
				return;

			for (go = part->dup_group->gobject.first; go; go = go->next)
				if (go->ob == par)
					return;
		}

		/* 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_check_group_weights(part);

		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
			 * BKE_object_where_is_calc_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 & no_draw_flag)
					continue;

				/* pa_num = pa->num; */ /* UNUSED */
				pa_time = pa->time;
				size = pa->size;
			}
			else {
				/* handle child particle */
				cpa = &psys->child[a - totpart];

				/* pa_num = a; */ /* UNUSED */
				pa_time = psys->particles[cpa->parent].time;
				size = psys_get_child_size(psys, cpa, ctime, NULL);
			}

			/* some hair paths might be non-existent so they can't be used for duplication */
			if (hair &&
			    ((a < totpart && psys->pathcache[a]->steps < 0) ||
			     (a >= totpart && psys->childcache[a - totpart]->steps < 0)))
			{
				continue;
			}

			if (part->ren_as == PART_DRAW_GR) {
				/* prevent divide by zero below [#28336] */
				if (totgroup == 0)
					continue;

				/* for groups, pick the object based on settings */
				if (part->draw & PART_DRAW_RAND_GR)
					b = BLI_rand() % 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, NULL, cache, pamat, &scale);
				}
				else {
					cache = psys->childcache[a - totpart];
					psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
				}

				copy_v3_v3(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;
				}
				else {
					float tquat[4];
					normalize_qt_qt(tquat, state.rot);
					quat_to_mat4(pamat, tquat);
					copy_v3_v3(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++) {

					copy_m4_m4(tmat, oblist[b]->obmat);
					/* apply particle scale */
					mul_mat3_m4_fl(tmat, size * scale);
					mul_v3_fl(tmat[3], size * scale);
					/* group dupli offset, should apply after everything else */
					if (!is_zero_v3(part->dup_group->dupli_ofs))
						sub_v3_v3v3(tmat[3], tmat[3], part->dup_group->dupli_ofs);
					/* individual particle transform */
					mult_m4_m4m4(tmat, pamat, tmat);

					if (par_space_mat)
						mult_m4_m4m4(mat, par_space_mat, tmat);
					else
						copy_m4_m4(mat, tmat);

					dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated);
					copy_m4_m4(dob->omat, obcopylist[b].obmat);
					if (G.rendering)
						psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
				}
			}
			else {
				/* to give ipos in object correct offset */
				BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);

				copy_v3_v3(vec, obmat[3]);
				obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;

				/* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
				if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
					float xvec[3], q[4];
					xvec[0] = -1.f;
					xvec[1] = xvec[2] = 0;
					vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
					quat_to_mat4(obmat, q);
					obmat[3][3] = 1.0f;
				}
				
				/* Normal particles and cached hair live in global space so we need to
				 * remove the real emitter's transformation before 2nd order duplication.
				 */
				if (par_space_mat && GS(id->name) != ID_GR)
					mult_m4_m4m4(mat, psys->imat, pamat);
				else
					copy_m4_m4(mat, pamat);

				mult_m4_m4m4(tmat, mat, obmat);
				mul_mat3_m4_fl(tmat, size * scale);

				if (par_space_mat)
					mult_m4_m4m4(mat, par_space_mat, tmat);
				else
					copy_m4_m4(mat, tmat);

				if (part->draw & PART_DRAW_GLOBAL_OB)
					add_v3_v3v3(mat[3], mat[3], vec);

				dob = new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
				copy_m4_m4(dob->omat, oldobmat);
				if (G.rendering)
					psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
			}
		}

		/* restore objects since they were changed in BKE_object_where_is_calc_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;
	}
}
Exemplo n.º 8
0
static int delete_exec(bContext *C, wmOperator *UNUSED(op))
{
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;

	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;
		int mask_layer_shape_ofs = 0;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		spline = masklay->splines.first;

		while (spline) {
			const int tot_point_orig = spline->tot_point;
			int i, count = 0;
			MaskSpline *next_spline = spline->next;

			/* count unselected points */
			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];

				if (!MASKPOINT_ISSEL_ANY(point))
					count++;
			}

			if (count == 0) {

				/* delete the whole spline */
				BLI_remlink(&masklay->splines, spline);
				BKE_mask_spline_free(spline);

				if (spline == masklay->act_spline) {
					masklay->act_spline = NULL;
					masklay->act_point = NULL;
				}

				BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
			}
			else {
				MaskSplinePoint *new_points;
				int j;

				new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints");

				for (i = 0, j = 0; i < tot_point_orig; i++) {
					MaskSplinePoint *point = &spline->points[i];

					if (!MASKPOINT_ISSEL_ANY(point)) {
						if (point == masklay->act_point)
							masklay->act_point = &new_points[j];

						delete_feather_points(point);

						new_points[j] = *point;
						j++;
					}
					else {
						if (point == masklay->act_point)
							masklay->act_point = NULL;

						BKE_mask_point_free(point);
						spline->tot_point--;

						BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
					}
				}

				mask_layer_shape_ofs += spline->tot_point;

				MEM_freeN(spline->points);
				spline->points = new_points;

				ED_mask_select_flush_all(mask);
			}

			spline = next_spline;
		}

		/* not essential but confuses users when there are keys with no data!
		 * assume if they delete all data from the layer they also dont care about keys */
		if (masklay->splines.first == NULL) {
			BKE_mask_layer_free_shapes(masklay);
		}
	}

	/* TODO: only update edited splines */
	BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra);

	WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);

	return OPERATOR_FINISHED;
}
Exemplo n.º 9
0
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
static DerivedMesh *fluidsim_read_obj(const char *filename)
{
	int wri = 0,i;
	int gotBytes;
	gzFile gzf;
	int numverts = 0, numfaces = 0;
	DerivedMesh *dm = NULL;
	MFace *mf;
	MVert *mv;
	short *normals, *no_s;
	float no[3];

	// ------------------------------------------------
	// get numverts + numfaces first
	// ------------------------------------------------
	gzf = gzopen(filename, "rb");
	if (!gzf)
	{
		return NULL;
	}

	// read numverts
	gotBytes = gzread(gzf, &wri, sizeof(wri));
	numverts = wri;

	// skip verts
	gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1;


	// read number of normals
	if(gotBytes)
		gotBytes = gzread(gzf, &wri, sizeof(wri));

	// skip normals
	gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1;

	/* get no. of triangles */
	if(gotBytes)
		gotBytes = gzread(gzf, &wri, sizeof(wri));
	numfaces = wri;

	gzclose( gzf );
	// ------------------------------------------------

	if(!numfaces || !numverts || !gotBytes)
		return NULL;

	gzf = gzopen(filename, "rb");
	if (!gzf)
	{
		return NULL;
	}

	dm = CDDM_new(numverts, 0, numfaces);

	if(!dm)
	{
		gzclose( gzf );
		return NULL;
	}

	// read numverts
	gotBytes = gzread(gzf, &wri, sizeof(wri));

	// read vertex position from file
	mv = CDDM_get_verts(dm);

	for(i=0; i<numverts; i++, mv++)
		gotBytes = gzread(gzf, mv->co, sizeof(float) * 3);

	// should be the same as numverts
	gotBytes = gzread(gzf, &wri, sizeof(wri));
	if(wri != numverts)
	{
		if(dm)
			dm->release(dm);
		gzclose( gzf );
		return NULL;
	}

	normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
	if(!normals)
	{
		if(dm)
			dm->release(dm);
		gzclose( gzf );
		return NULL;
	}

	// read normals from file (but don't save them yet)
	for(i=numverts, no_s= normals; i>0; i--, no_s += 3)
	{
		gotBytes = gzread(gzf, no, sizeof(float) * 3);
		normal_float_to_short_v3(no_s, no);
	}

	/* read no. of triangles */
	gotBytes = gzread(gzf, &wri, sizeof(wri));

	if(wri!=numfaces) {
		printf("Fluidsim: error in reading data from file.\n");
		if(dm)
			dm->release(dm);
		gzclose( gzf );
		MEM_freeN(normals);
		return NULL;
	}

	// read triangles from file
	mf = CDDM_get_faces(dm);
	for(i=numfaces; i>0; i--, mf++)
	{
		int face[3];

		gotBytes = gzread(gzf, face, sizeof(int) * 3);

		// check if 3rd vertex has index 0 (not allowed in blender)
		if(face[2])
		{
			mf->v1 = face[0];
			mf->v2 = face[1];
			mf->v3 = face[2];
		}
		else
		{
			mf->v1 = face[1];
			mf->v2 = face[2];
			mf->v3 = face[0];
		}
		mf->v4 = 0;

		test_index_face(mf, NULL, 0, 3);
	}

	gzclose( gzf );

	CDDM_calc_edges(dm);

	CDDM_apply_vert_normals(dm, (short (*)[3])normals);
	MEM_freeN(normals);

	// CDDM_calc_normals(result);

	return dm;
}
Exemplo n.º 10
0
void get_texture_coords(MappingInfoModifierData *dmd, Object *ob,
                        DerivedMesh *dm,
                        float (*co)[3], float (*texco)[3],
                        int numVerts)
{
	int i;
	int texmapping = dmd->texmapping;
	float mapob_imat[4][4];

	if(texmapping == MOD_DISP_MAP_OBJECT) {
		if(dmd->map_object)
			invert_m4_m4(mapob_imat, dmd->map_object->obmat);
		else /* if there is no map object, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	/* UVs need special handling, since they come from faces */
	if(texmapping == MOD_DISP_MAP_UV) {
		if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
			MFace *mface = dm->getFaceArray(dm);
			MFace *mf;
			char *done = MEM_callocN(sizeof(*done) * numVerts,
			                         "get_texture_coords done");
			int numFaces = dm->getNumFaces(dm);
			char uvname[32];
			MTFace *tf;

			validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);

			/* verts are given the UV from the first face that uses them */
			for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
				if(!done[mf->v1]) {
					texco[mf->v1][0] = tf->uv[0][0];
					texco[mf->v1][1] = tf->uv[0][1];
					texco[mf->v1][2] = 0;
					done[mf->v1] = 1;
				}
				if(!done[mf->v2]) {
					texco[mf->v2][0] = tf->uv[1][0];
					texco[mf->v2][1] = tf->uv[1][1];
					texco[mf->v2][2] = 0;
					done[mf->v2] = 1;
				}
				if(!done[mf->v3]) {
					texco[mf->v3][0] = tf->uv[2][0];
					texco[mf->v3][1] = tf->uv[2][1];
					texco[mf->v3][2] = 0;
					done[mf->v3] = 1;
				}
				if(!done[mf->v4]) {
					texco[mf->v4][0] = tf->uv[3][0];
					texco[mf->v4][1] = tf->uv[3][1];
					texco[mf->v4][2] = 0;
					done[mf->v4] = 1;
				}
			}

			/* remap UVs from [0, 1] to [-1, 1] */
			for(i = 0; i < numVerts; ++i) {
				texco[i][0] = texco[i][0] * 2 - 1;
				texco[i][1] = texco[i][1] * 2 - 1;
			}

			MEM_freeN(done);
			return;
		} else /* if there are no UVs, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	for(i = 0; i < numVerts; ++i, ++co, ++texco) {
		switch(texmapping) {
		case MOD_DISP_MAP_LOCAL:
			copy_v3_v3(*texco, *co);
			break;
		case MOD_DISP_MAP_GLOBAL:
			mul_v3_m4v3(*texco, ob->obmat, *co);
			break;
		case MOD_DISP_MAP_OBJECT:
			mul_v3_m4v3(*texco, ob->obmat, *co);
			mul_m4_v3(mapob_imat, *texco);
			break;
		}
	}
}
Exemplo n.º 11
0
static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	SlidePointData *customdata = NULL;
	MaskLayer *masklay, *cv_masklay, *feather_masklay;
	MaskSpline *spline, *cv_spline, *feather_spline;
	MaskSplinePoint *point, *cv_point, *feather_point;
	MaskSplinePointUW *uw = NULL;
	int is_handle = FALSE, width, height, action = SLIDE_ACTION_NONE;
	int slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
	float co[2], cv_score, feather_score;
	const float threshold = 19;

	ED_mask_mouse_pos(sa, ar, event, co);
	ED_mask_get_size(sa, &width, &height);

	cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score);

	if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
		if (slide_feather || !cv_point || feather_score < cv_score) {
			action = SLIDE_ACTION_FEATHER;

			masklay = feather_masklay;
			spline = feather_spline;
			point = feather_point;
		}
	}

	if (cv_point && action == SLIDE_ACTION_NONE) {
		if (is_handle)
			action = SLIDE_ACTION_HANDLE;
		else
			action = SLIDE_ACTION_POINT;

		masklay = cv_masklay;
		spline = cv_spline;
		point = cv_point;
	}

	if (action != SLIDE_ACTION_NONE) {
		customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");

		customdata->mask = mask;
		customdata->masklay = masklay;
		customdata->spline = spline;
		customdata->point = point;
		customdata->width = width;
		customdata->height = height;
		customdata->action = action;
		customdata->uw = uw;

		if (uw) {
			float co[2];
			float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);

			customdata->weight = uw->w;
			customdata->weight_scalar = weight_scalar;
			BKE_mask_point_segment_co(spline, point, uw->u, co);
			BKE_mask_point_normal(spline, point, uw->u, customdata->no);

			madd_v2_v2v2fl(customdata->feather, co, customdata->no, uw->w * weight_scalar);
		}
		else {
			BezTriple *bezt = &point->bezt;

			customdata->weight = bezt->weight;
			customdata->weight_scalar = 1.0f;
			BKE_mask_point_normal(spline, point, 0.0f, customdata->no);

			madd_v2_v2v2fl(customdata->feather, bezt->vec[1], customdata->no, bezt->weight);
		}

		if (customdata->action == SLIDE_ACTION_FEATHER)
			customdata->initial_feather = slide_point_check_initial_feather(spline);

		copy_m3_m3(customdata->vec, point->bezt.vec);
		if (BKE_mask_point_has_handle(point))
			BKE_mask_point_handle(point, customdata->handle);
		ED_mask_mouse_pos(sa, ar, event, customdata->co);
	}

	return customdata;
}
Exemplo n.º 12
0
void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
{
	BPoint *bp;
	int i, u, v, w;
	float fu, fv, fw, uc, vc, wc, du = 0.0, dv = 0.0, dw = 0.0;
	float *co, (*vertexCos)[3] = NULL;
	
	/* vertex weight groups are just freed all for now */
	if (lt->dvert) {
		BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
		lt->dvert = NULL;
	}
	
	while (uNew * vNew * wNew > 32000) {
		if (uNew >= vNew && uNew >= wNew) uNew--;
		else if (vNew >= uNew && vNew >= wNew) vNew--;
		else wNew--;
	}

	vertexCos = MEM_mallocN(sizeof(*vertexCos) * uNew * vNew * wNew, "tmp_vcos");

	calc_lat_fudu(lt->flag, uNew, &fu, &du);
	calc_lat_fudu(lt->flag, vNew, &fv, &dv);
	calc_lat_fudu(lt->flag, wNew, &fw, &dw);

	/* If old size is different then resolution changed in interface,
	 * try to do clever reinit of points. Pretty simply idea, we just
	 * deform new verts by old lattice, but scaling them to match old
	 * size first.
	 */
	if (ltOb) {
		if (uNew != 1 && lt->pntsu != 1) {
			fu = lt->fu;
			du = (lt->pntsu - 1) * lt->du / (uNew - 1);
		}

		if (vNew != 1 && lt->pntsv != 1) {
			fv = lt->fv;
			dv = (lt->pntsv - 1) * lt->dv / (vNew - 1);
		}

		if (wNew != 1 && lt->pntsw != 1) {
			fw = lt->fw;
			dw = (lt->pntsw - 1) * lt->dw / (wNew - 1);
		}
	}

	co = vertexCos[0];
	for (w = 0, wc = fw; w < wNew; w++, wc += dw) {
		for (v = 0, vc = fv; v < vNew; v++, vc += dv) {
			for (u = 0, uc = fu; u < uNew; u++, co += 3, uc += du) {
				co[0] = uc;
				co[1] = vc;
				co[2] = wc;
			}
		}
	}
	
	if (ltOb) {
		float mat[4][4];
		int typeu = lt->typeu, typev = lt->typev, typew = lt->typew;

		/* works best if we force to linear type (endpoints match) */
		lt->typeu = lt->typev = lt->typew = KEY_LINEAR;

		/* prevent using deformed locations */
		BKE_displist_free(&ltOb->curve_cache->disp);

		copy_m4_m4(mat, ltOb->obmat);
		unit_m4(ltOb->obmat);
		lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew * vNew * wNew, NULL, 1.0f);
		copy_m4_m4(ltOb->obmat, mat);

		lt->typeu = typeu;
		lt->typev = typev;
		lt->typew = typew;
	}

	lt->fu = fu;
	lt->fv = fv;
	lt->fw = fw;
	lt->du = du;
	lt->dv = dv;
	lt->dw = dw;

	lt->pntsu = uNew;
	lt->pntsv = vNew;
	lt->pntsw = wNew;

	lt->actbp = LT_ACTBP_NONE;
	MEM_freeN(lt->def);
	lt->def = MEM_callocN(lt->pntsu * lt->pntsv * lt->pntsw * sizeof(BPoint), "lattice bp");
	
	bp = lt->def;
	
	for (i = 0; i < lt->pntsu * lt->pntsv * lt->pntsw; i++, bp++) {
		copy_v3_v3(bp->vec, vertexCos[i]);
	}

	MEM_freeN(vertexCos);
}
Exemplo n.º 13
0
static void sss_create_tree_mat(Render *re, Material *mat)
{
	SSSPoints *p;
	RenderResult *rr;
	ListBase points;
	float (*co)[3] = NULL, (*color)[3] = NULL, *area = NULL;
	int totpoint = 0, osa, osaflag, partsdone;

	if (re->test_break(re->tbh))
		return;
	
	points.first= points.last= NULL;

	/* TODO: this is getting a bit ugly, copying all those variables and
	 * setting them back, maybe we need to create our own Render? */

	/* do SSS preprocessing render */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	rr= re->result;
	osa= re->osa;
	osaflag= re->r.mode & R_OSA;
	partsdone= re->i.partsdone;

	re->osa= 0;
	re->r.mode &= ~R_OSA;
	re->sss_points= &points;
	re->sss_mat= mat;
	re->i.partsdone = FALSE;

	if (!(re->r.scemode & R_PREVIEWBUTS))
		re->result= NULL;
	BLI_rw_mutex_unlock(&re->resultmutex);

	RE_TileProcessor(re);
	
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if (!(re->r.scemode & R_PREVIEWBUTS)) {
		RE_FreeRenderResult(re->result);
		re->result= rr;
	}
	BLI_rw_mutex_unlock(&re->resultmutex);

	re->i.partsdone= partsdone;
	re->sss_mat= NULL;
	re->sss_points= NULL;
	re->osa= osa;
	if (osaflag) re->r.mode |= R_OSA;

	/* no points? no tree */
	if (!points.first)
		return;

	/* merge points together into a single buffer */
	if (!re->test_break(re->tbh)) {
		for (totpoint=0, p=points.first; p; p=p->next)
			totpoint += p->totpoint;
		
		co= MEM_mallocN(sizeof(*co)*totpoint, "SSSCo");
		color= MEM_mallocN(sizeof(*color)*totpoint, "SSSColor");
		area= MEM_mallocN(sizeof(*area)*totpoint, "SSSArea");

		for (totpoint=0, p=points.first; p; p=p->next) {
			memcpy(co+totpoint, p->co, sizeof(*co)*p->totpoint);
			memcpy(color+totpoint, p->color, sizeof(*color)*p->totpoint);
			memcpy(area+totpoint, p->area, sizeof(*area)*p->totpoint);
			totpoint += p->totpoint;
		}
	}

	/* free points */
	for (p=points.first; p; p=p->next) {
		MEM_freeN(p->co);
		MEM_freeN(p->color);
		MEM_freeN(p->area);
	}
	BLI_freelistN(&points);

	/* build tree */
	if (!re->test_break(re->tbh)) {
		SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData");
		float ior= mat->sss_ior, cfac= mat->sss_colfac;
		float *radius= mat->sss_radius;
		float fw= mat->sss_front, bw= mat->sss_back;
		float error = mat->sss_error;

		error= get_render_aosss_error(&re->r, error);
		if ((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f)
			error= 0.5f;
		
		sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw);
		sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw);
		sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw);
		sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error,
			co, color, area, totpoint);

		MEM_freeN(co);
		MEM_freeN(color);
		MEM_freeN(area);

		scatter_tree_build(sss->tree);

		BLI_ghash_insert(re->sss_hash, mat, sss);
	}
	else {
		if (co) MEM_freeN(co);
		if (color) MEM_freeN(color);
		if (area) MEM_freeN(area);
	}
}
Exemplo n.º 14
0
Arquivo: smoke.c Projeto: jinjoh/NOOR
void smokeModifier_createType(struct SmokeModifierData *smd)
{
	if(smd)
	{
		if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
		{
			if(smd->domain)
				smokeModifier_freeDomain(smd);

			smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");

			smd->domain->smd = smd;

			smd->domain->point_cache[0] = BKE_ptcache_add(&(smd->domain->ptcaches[0]));
			smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
			smd->domain->point_cache[0]->step = 1;

			smd->domain->point_cache[1] = BKE_ptcache_add(&(smd->domain->ptcaches[1]));
			smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE;
			smd->domain->point_cache[1]->step = 1;

			/* set some standard values */
			smd->domain->fluid = NULL;
			smd->domain->wt = NULL;			
			smd->domain->eff_group = NULL;
			smd->domain->fluid_group = NULL;
			smd->domain->coll_group = NULL;
			smd->domain->maxres = 32;
			smd->domain->amplify = 1;			
			smd->domain->omega = 1.0;			
			smd->domain->alpha = -0.001;
			smd->domain->beta = 0.1;
			smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
			smd->domain->strength = 2.0;
			smd->domain->noise = MOD_SMOKE_NOISEWAVE;
			smd->domain->diss_speed = 5;
			// init 3dview buffer
			smd->domain->viewsettings = 0;
			smd->domain->effector_weights = BKE_add_effector_weights(NULL);
		}
		else if(smd->type & MOD_SMOKE_TYPE_FLOW)
		{
			if(smd->flow)
				smokeModifier_freeFlow(smd);

			smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");

			smd->flow->smd = smd;

			/* set some standard values */
			smd->flow->density = 1.0;
			smd->flow->temp = 1.0;

			smd->flow->psys = NULL;

		}
		else if(smd->type & MOD_SMOKE_TYPE_COLL)
		{
			if(smd->coll)
				smokeModifier_freeCollision(smd);

			smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");

			smd->coll->smd = smd;
			smd->coll->points = NULL;
			smd->coll->numpoints = 0;
			smd->coll->bvhtree = NULL;
			smd->coll->dm = NULL;
		}
	}
}
Exemplo n.º 15
0
/* Edge-Length Weighted Smoothing
 */
static void smooth_iter__length_weight(
    CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
    float (*vertexCos)[3], unsigned int numVerts,
    const float *smooth_weights,
    unsigned int iterations)
{
    const float eps = FLT_EPSILON * 10.0f;
    const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
    /* note: the way this smoothing method works, its approx half as strong as the simple-smooth,
     * and 2.0 rarely spikes, double the value for consistent behavior. */
    const float lambda = csmd->lambda * 2.0f;
    const MEdge *edges = dm->getEdgeArray(dm);
    float *vertex_edge_count;
    unsigned int i;

    struct SmoothingData_Weighted {
        float delta[3];
        float edge_length_sum;
    } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__);


    /* calculate as floats to avoid int->float conversion in #smooth_iter */
    vertex_edge_count = MEM_callocN((size_t)numVerts * sizeof(float), __func__);
    for (i = 0; i < numEdges; i++) {
        vertex_edge_count[edges[i].v1] += 1.0f;
        vertex_edge_count[edges[i].v2] += 1.0f;
    }


    /* -------------------------------------------------------------------- */
    /* Main Smoothing Loop */

    while (iterations--) {
        for (i = 0; i < numEdges; i++) {
            struct SmoothingData_Weighted *sd_v1;
            struct SmoothingData_Weighted *sd_v2;
            float edge_dir[3];
            float edge_dist;

            sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]);
            edge_dist = len_v3(edge_dir);

            /* weight by distance */
            mul_v3_fl(edge_dir, edge_dist);


            sd_v1 = &smooth_data[edges[i].v1];
            sd_v2 = &smooth_data[edges[i].v2];

            add_v3_v3(sd_v1->delta, edge_dir);
            sub_v3_v3(sd_v2->delta, edge_dir);

            sd_v1->edge_length_sum += edge_dist;
            sd_v2->edge_length_sum += edge_dist;
        }

        if (smooth_weights == NULL) {
            /* fast-path */
            for (i = 0; i < numVerts; i++) {
                struct SmoothingData_Weighted *sd = &smooth_data[i];
                /* divide by sum of all neighbour distances (weighted) and amount of neighbors, (mean average) */
                const float div = sd->edge_length_sum * vertex_edge_count[i];
                if (div > eps) {
#if 0
                    /* first calculate the new location */
                    mul_v3_fl(sd->delta, 1.0f / div);
                    /* then interpolate */
                    madd_v3_v3fl(vertexCos[i], sd->delta, lambda);
#else
                    /* do this in one step */
                    madd_v3_v3fl(vertexCos[i], sd->delta, lambda / div);
#endif
                }
                /* zero for the next iteration (saves memset on entire array) */
                memset(sd, 0, sizeof(*sd));
            }
        }
        else {
            for (i = 0; i < numVerts; i++) {
                struct SmoothingData_Weighted *sd = &smooth_data[i];
                const float div = sd->edge_length_sum * vertex_edge_count[i];
                if (div > eps) {
                    const float lambda_w = lambda * smooth_weights[i];
                    madd_v3_v3fl(vertexCos[i], sd->delta, lambda_w / div);
                }

                memset(sd, 0, sizeof(*sd));
            }
        }
    }

    MEM_freeN(vertex_edge_count);
    MEM_freeN(smooth_data);
}
Exemplo n.º 16
0
void fluidsim_init(FluidsimModifierData *fluidmd)
{
#ifdef WITH_MOD_FLUID
	if(fluidmd)
	{
		FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");

		fluidmd->fss = fss;
		
		if(!fss)
			return;
		
		fss->fmd = fluidmd;
		fss->type = OB_FLUIDSIM_ENABLE;
		fss->show_advancedoptions = 0;

		fss->resolutionxyz = 65;
		fss->previewresxyz = 45;
		fss->realsize = 0.5;
		fss->guiDisplayMode = 2; // preview
		fss->renderDisplayMode = 3; // render

		fss->viscosityMode = 2; // default to water
		fss->viscosityValue = 1.0;
		fss->viscosityExponent = 6;
		
		fss->grav[0] = 0.0;
		fss->grav[1] = 0.0;
		fss->grav[2] = -9.81;

		fss->animStart = 0.0; 
		fss->animEnd = 4.0;
		fss->animRate = 1.0;
		fss->gstar = 0.005; // used as normgstar
		fss->maxRefine = -1;
		// maxRefine is set according to resolutionxyz during bake

		// fluid/inflow settings
		// fss->iniVel --> automatically set to 0

		modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), "cache_fluid");

		// first init of bounding box
		// no bounding box needed
		
		// todo - reuse default init from elbeem!
		fss->typeFlags = OB_FSBND_PARTSLIP | OB_FSSG_NOOBS;
		fss->domainNovecgen = 0;
		fss->volumeInitType = 1; // volume
		fss->partSlipValue = 0.2;

		fss->generateTracers = 0;
		fss->generateParticles = 0.0;
		fss->surfaceSmoothing = 1.0;
		fss->surfaceSubdivs = 0.0;
		fss->particleInfSize = 0.0;
		fss->particleInfAlpha = 0.0;
	
		// init fluid control settings
		fss->attractforceStrength = 0.2;
		fss->attractforceRadius = 0.75;
		fss->velocityforceStrength = 0.2;
		fss->velocityforceRadius = 0.75;
		fss->cpsTimeStart = fss->animStart;
		fss->cpsTimeEnd = fss->animEnd;
		fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
		
		/*
		BAD TODO: this is done in buttons_object.c in the moment 
		Mesh *mesh = ob->data;
		// calculate bounding box
		fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);	
		*/
		
		fss->meshVelocities = NULL;
		
		fss->lastgoodframe = -1;
		
		fss->flag |= OB_FLUIDSIM_ACTIVE;

	}
#else
	(void)fluidmd; /* unused */
#endif
	return;
}
Exemplo n.º 17
0
static void correctivesmooth_modifier_do(
    ModifierData *md, Object *ob, DerivedMesh *dm,
    float (*vertexCos)[3], unsigned int numVerts,
    struct BMEditMesh *em)
{
    CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;

    const bool force_delta_cache_update =
        /* XXX, take care! if mesh data its self changes we need to forcefully recalculate deltas */
        ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) &&
         (((ID *)ob->data)->tag & LIB_TAG_ID_RECALC));

    bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0;
    MDeformVert *dvert = NULL;
    int defgrp_index;

    modifier_get_vgroup(ob, dm, csmd->defgrp_name, &dvert, &defgrp_index);

    /* if rest bind_coords not are defined, set them (only run during bind) */
    if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
            /* signal to recalculate, whoever sets MUST also free bind coords */
            (csmd->bind_coords_num == (unsigned int)-1))
    {
        BLI_assert(csmd->bind_coords == NULL);
        csmd->bind_coords = MEM_dupallocN(vertexCos);
        csmd->bind_coords_num = numVerts;
        BLI_assert(csmd->bind_coords != NULL);
    }

    if (UNLIKELY(use_only_smooth)) {
        smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);
        return;
    }

    if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) {
        modifier_setError(md, "Bind data required");
        goto error;
    }

    /* If the number of verts has changed, the bind is invalid, so we do nothing */
    if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
        if (csmd->bind_coords_num != numVerts) {
            modifier_setError(md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts);
            goto error;
        }
    }
    else {
        /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */
        if (ob->type != OB_MESH) {
            modifier_setError(md, "Object is not a mesh");
            goto error;
        }
        else {
            unsigned int me_numVerts = (unsigned int)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert);

            if (me_numVerts != numVerts) {
                modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts);
                goto error;
            }
        }
    }

    /* check to see if our deltas are still valid */
    if (!csmd->delta_cache || (csmd->delta_cache_num != numVerts) || force_delta_cache_update) {
        const float (*rest_coords)[3];
        bool is_rest_coords_alloc = false;

        if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
            /* caller needs to do sanity check here */
            csmd->bind_coords_num = numVerts;
            rest_coords = (const float (*)[3])csmd->bind_coords;
        }
        else {
            int me_numVerts;
            rest_coords = (const float (*)[3]) ((em) ?
                                                BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) :
                                                BKE_mesh_vertexCos_get(ob->data, &me_numVerts));

            BLI_assert((unsigned int)me_numVerts == numVerts);
            is_rest_coords_alloc = true;
        }

#ifdef DEBUG_TIME
        TIMEIT_START(corrective_smooth_deltas);
#endif

        calc_deltas(csmd, dm, dvert, defgrp_index, rest_coords, numVerts);

#ifdef DEBUG_TIME
        TIMEIT_END(corrective_smooth_deltas);
#endif
        if (is_rest_coords_alloc) {
            MEM_freeN((void *)rest_coords);
        }
    }

    if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
        /* this could be a check, but at this point it _must_ be valid */
        BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache);
    }


#ifdef DEBUG_TIME
    TIMEIT_START(corrective_smooth);
#endif

    /* do the actual delta mush */
    smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);

    {
        unsigned int i;

        float (*tangent_spaces)[3][3];

        /* calloc, since values are accumulated */
        tangent_spaces = MEM_callocN((size_t)numVerts * sizeof(float[3][3]), __func__);

        calc_tangent_spaces(dm, vertexCos, tangent_spaces);

        for (i = 0; i < numVerts; i++) {
            float delta[3];

#ifdef USE_TANGENT_CALC_INLINE
            calc_tangent_ortho(tangent_spaces[i]);
#endif

            mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache[i]);
            add_v3_v3(vertexCos[i], delta);
        }

        MEM_freeN(tangent_spaces);
    }

#ifdef DEBUG_TIME
    TIMEIT_END(corrective_smooth);
#endif

    return;

    /* when the modifier fails to execute */
error:
    MEM_SAFE_FREE(csmd->delta_cache);
    csmd->delta_cache_num = 0;

}
Exemplo n.º 18
0
ThreadRWMutex *BLI_rw_mutex_alloc(void)
{
	ThreadRWMutex *mutex = MEM_callocN(sizeof(ThreadRWMutex), "ThreadRWMutex");
	BLI_rw_mutex_init(mutex);
	return mutex;
}
Exemplo n.º 19
0
/**
 * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
 *
 * \return false if no changes needed to be made.
 */
bool BKE_mesh_validate_arrays(Mesh *mesh,
                              MVert *mverts, unsigned int totvert,
                              MEdge *medges, unsigned int totedge,
                              MFace *mfaces, unsigned int totface,
                              MLoop *mloops, unsigned int totloop,
                              MPoly *mpolys, unsigned int totpoly,
                              MDeformVert *dverts, /* assume totvert length */
                              const bool do_verbose, const bool do_fixes,
                              bool *r_change)
{
#   define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0
#   define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)

#   define REMOVE_LOOP_TAG(_ml) { _ml->e = INVALID_LOOP_EDGE_MARKER; do_polyloop_free = true; } (void)0
#   define REMOVE_POLY_TAG(_mp) { _mp->totloop *= -1; do_polyloop_free = true; } (void)0

	MVert *mv = mverts;
	MEdge *me;
	MLoop *ml;
	MPoly *mp;
	unsigned int i, j;
	int *v;

	bool is_valid = true;

	bool do_edge_free = false;
	bool do_face_free = false;
	bool do_polyloop_free = false; /* This regroups loops and polys! */

	bool verts_fixed = false;
	bool vert_weights_fixed = false;
	bool msel_fixed = false;

	bool do_edge_recalc = false;

	EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge);

	BLI_assert(!(do_fixes && mesh == NULL));

	PRINT_MSG("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n",
	          __func__, totvert, totedge, totloop, totpoly);

	if (totedge == 0 && totpoly != 0) {
		PRINT_ERR("\tLogical error, %u polygons and 0 edges\n", totpoly);
		do_edge_recalc = do_fixes;
	}

	for (i = 1; i < totvert; i++, mv++) {
		int fix_normal = TRUE;

		for (j = 0; j < 3; j++) {
			if (!finite(mv->co[j])) {
				PRINT_ERR("\tVertex %u: has invalid coordinate\n", i);

				if (do_fixes) {
					zero_v3(mv->co);

					verts_fixed = TRUE;
				}
			}

			if (mv->no[j] != 0)
				fix_normal = FALSE;
		}

		if (fix_normal) {
			PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal\n", i);
			if (do_fixes) {
				mv->no[2] = SHRT_MAX;
				verts_fixed = TRUE;
			}
		}
	}

	for (i = 0, me = medges; i < totedge; i++, me++) {
		int remove = FALSE;
		if (me->v1 == me->v2) {
			PRINT_ERR("\tEdge %u: has matching verts, both %u\n", i, me->v1);
			remove = do_fixes;
		}
		if (me->v1 >= totvert) {
			PRINT_ERR("\tEdge %u: v1 index out of range, %u\n", i, me->v1);
			remove = do_fixes;
		}
		if (me->v2 >= totvert) {
			PRINT_ERR("\tEdge %u: v2 index out of range, %u\n", i, me->v2);
			remove = do_fixes;
		}

		if (BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) {
			PRINT_ERR("\tEdge %u: is a duplicate of %d\n", i,
			          GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2)));
			remove = do_fixes;
		}

		if (remove == FALSE) {
			BLI_edgehash_insert(edge_hash, me->v1, me->v2, SET_INT_IN_POINTER(i));
		}
		else {
			REMOVE_EDGE_TAG(me);
		}
	}

	if (mfaces && !mpolys) {
#		define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; do_face_free = TRUE; } (void)0
#		define CHECK_FACE_VERT_INDEX(a, b) \
					if (mf->a == mf->b) { \
						PRINT_ERR("    face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \
						remove = do_fixes; \
					} (void)0
#		define CHECK_FACE_EDGE(a, b) \
					if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \
						PRINT_ERR("    face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \
						          " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \
						do_edge_recalc = TRUE; \
					} (void)0

		MFace *mf;
		MFace *mf_prev;

		SortFace *sort_faces = MEM_callocN(sizeof(SortFace) * totface, "search faces");
		SortFace *sf;
		SortFace *sf_prev;
		unsigned int totsortface = 0;

		PRINT_ERR("No Polys, only tesselated Faces\n");

		for (i = 0, mf = mfaces, sf = sort_faces; i < totface; i++, mf++) {
			int remove = FALSE;
			int fidx;
			unsigned int fv[4];

			fidx = mf->v4 ? 3 : 2;
			do {
				fv[fidx] = *(&(mf->v1) + fidx);
				if (fv[fidx] >= totvert) {
					PRINT_ERR("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
					remove = do_fixes;
				}
			} while (fidx--);

			if (remove == FALSE) {
				if (mf->v4) {
					CHECK_FACE_VERT_INDEX(v1, v2);
					CHECK_FACE_VERT_INDEX(v1, v3);
					CHECK_FACE_VERT_INDEX(v1, v4);

					CHECK_FACE_VERT_INDEX(v2, v3);
					CHECK_FACE_VERT_INDEX(v2, v4);

					CHECK_FACE_VERT_INDEX(v3, v4);
				}
				else {
					CHECK_FACE_VERT_INDEX(v1, v2);
					CHECK_FACE_VERT_INDEX(v1, v3);

					CHECK_FACE_VERT_INDEX(v2, v3);
				}

				if (remove == FALSE) {
					if (totedge) {
						if (mf->v4) {
							CHECK_FACE_EDGE(v1, v2);
							CHECK_FACE_EDGE(v2, v3);
							CHECK_FACE_EDGE(v3, v4);
							CHECK_FACE_EDGE(v4, v1);
						}
						else {
							CHECK_FACE_EDGE(v1, v2);
							CHECK_FACE_EDGE(v2, v3);
							CHECK_FACE_EDGE(v3, v1);
						}
					}

					sf->index = i;

					if (mf->v4) {
						edge_store_from_mface_quad(sf->es, mf);

						qsort(sf->es, 4, sizeof(int64_t), int64_cmp);
					}
					else {
						edge_store_from_mface_tri(sf->es, mf);
						qsort(sf->es, 3, sizeof(int64_t), int64_cmp);
					}

					totsortface++;
					sf++;
				}
			}

			if (remove) {
				REMOVE_FACE_TAG(mf);
			}
		}

		qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp);

		sf = sort_faces;
		sf_prev = sf;
		sf++;

		for (i = 1; i < totsortface; i++, sf++) {
			int remove = FALSE;

			/* on a valid mesh, code below will never run */
			if (memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) {
				mf = mfaces + sf->index;

				if (do_verbose) {
					mf_prev = mfaces + sf_prev->index;

					if (mf->v4) {
						PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n",
						          sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4,
						          mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
					}
					else {
						PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n",
						          sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3,
						          mf_prev->v1, mf_prev->v2, mf_prev->v3);
					}
				}

				remove = do_fixes;
			}
			else {
				sf_prev = sf;
			}

			if (remove) {
				REMOVE_FACE_TAG(mf);
			}
		}

		MEM_freeN(sort_faces);

#		undef REMOVE_FACE_TAG
#		undef CHECK_FACE_VERT_INDEX
#		undef CHECK_FACE_EDGE
	}

	/* Checking loops and polys is a bit tricky, as they are quite intricated...
	 *
	 * Polys must have:
	 * - a valid loopstart value.
	 * - a valid totloop value (>= 3 and loopstart+totloop < me.totloop).
	 *
	 * Loops must have:
	 * - a valid v value.
	 * - a valid e value (corresponding to the edge it defines with the next loop in poly).
	 *
	 * Also, loops not used by polys can be discarded.
	 * And "intersecting" loops (i.e. loops used by more than one poly) are invalid,
	 * so be sure to leave at most one poly per loop!
	 */
	{
		SortPoly *sort_polys = MEM_callocN(sizeof(SortPoly) * totpoly, "mesh validate's sort_polys");
		SortPoly *prev_sp, *sp = sort_polys;
		int prev_end;
		for (i = 0, mp = mpolys; i < totpoly; i++, mp++, sp++) {
			sp->index = i;

			if (mp->loopstart < 0 || mp->totloop < 3) {
				/* Invalid loop data. */
				PRINT_ERR("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n",
				          sp->index, mp->loopstart, mp->totloop);
				sp->invalid = TRUE;
			}
			else if (mp->loopstart + mp->totloop > totloop) {
				/* Invalid loop data. */
				PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n",
				          sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1);
				sp->invalid = TRUE;
			}
			else {
				/* Poly itself is valid, for now. */
				int v1, v2; /* v1 is prev loop vert idx, v2 is current loop one. */
				sp->invalid = FALSE;
				sp->verts = v = MEM_mallocN(sizeof(int) * mp->totloop, "Vert idx of SortPoly");
				sp->numverts = mp->totloop;
				sp->loopstart = mp->loopstart;

				/* Test all poly's loops' vert idx. */
				for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++, v++) {
					if (ml->v >= totvert) {
						/* Invalid vert idx. */
						PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
						sp->invalid = TRUE;
					}

					mverts[ml->v].flag |= ME_VERT_TMP_TAG;
					*v = ml->v;
				}

				/* is the same vertex used more than once */
				if (!sp->invalid) {
					v = sp->verts;
					for (j = 0; j < mp->totloop; j++, v++) {
						if ((mverts[*v].flag & ME_VERT_TMP_TAG) == 0) {
							PRINT_ERR("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j);
							sp->invalid = TRUE;
						}
						mverts[*v].flag &= ~ME_VERT_TMP_TAG;
					}
				}

				if (sp->invalid)
					continue;

				/* Test all poly's loops. */
				for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++) {
					v1 = ml->v;
					v2 = mloops[sp->loopstart + (j + 1) % mp->totloop].v;
					if (!BLI_edgehash_haskey(edge_hash, v1, v2)) {
						/* Edge not existing. */
						PRINT_ERR("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2);
						if (do_fixes)
							do_edge_recalc = TRUE;
						else
							sp->invalid = TRUE;
					}
					else if (ml->e >= totedge) {
						/* Invalid edge idx.
						 * We already know from previous text that a valid edge exists, use it (if allowed)! */
						if (do_fixes) {
							int prev_e = ml->e;
							ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
							PRINT_ERR("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n",
							          sp->loopstart + j, prev_e, ml->e);
						}
						else {
							PRINT_ERR("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e);
							sp->invalid = TRUE;
						}
					}
					else {
						me = &medges[ml->e];
						if (IS_REMOVED_EDGE(me) || !((me->v1 == v1 && me->v2 == v2) || (me->v1 == v2 && me->v2 == v1))) {
							/* The pointed edge is invalid (tagged as removed, or vert idx mismatch),
							 * and we already know from previous test that a valid one exists, use it (if allowed)! */
							if (do_fixes) {
								int prev_e = ml->e;
								ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
								PRINT_ERR("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n",
								          sp->index, prev_e, ml->e);
							}
							else {
								PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e);
								sp->invalid = TRUE;
							}
						}
					}
				}

				/* Now check that that poly does not use a same vertex more than once! */
				if (!sp->invalid) {
					int *prev_v = v = sp->verts;
					j = sp->numverts;

					qsort(sp->verts, j, sizeof(int), int_cmp);

					for (j--, v++; j; j--, v++) {
						if (*v != *prev_v) {
							int dlt = v - prev_v;
							if (dlt > 1) {
								PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
								          sp->index, *prev_v, dlt);
								sp->invalid = TRUE;
							}
							prev_v = v;
						}
					}
					if (v - prev_v > 1) { /* Don't forget final verts! */
						PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
						          sp->index, *prev_v, (int)(v - prev_v));
						sp->invalid = TRUE;
					}
				}
			
			}
		}

		/* Second check pass, testing polys using the same verts. */
		qsort(sort_polys, totpoly, sizeof(SortPoly), search_poly_cmp);
		sp = prev_sp = sort_polys;
		sp++;

		for (i = 1; i < totpoly; i++, sp++) {
			int p1_nv = sp->numverts, p2_nv = prev_sp->numverts;
			int *p1_v = sp->verts, *p2_v = prev_sp->verts;
			short p1_sub = TRUE, p2_sub = TRUE;
			if (sp->invalid)
				break;
			/* Test same polys. */
#if 0
			/* NOTE: This performs a sub-set test. */
			/* XXX This (and the sort of verts list) is better than systematic
			 *     search of all verts of one list into the other if lists have
			 *     a fair amount of elements.
			 *     Not sure however it's worth it in this case?
			 *     But as we also need sorted vert list to check verts multi-used
			 *     (in first pass of checks)... */
			/* XXX If we consider only "equal" polys (i.e. using exactly same set of verts)
			 *     as invalid, better to replace this by a simple memory cmp... */
			while ((p1_nv && p2_nv) && (p1_sub || p2_sub)) {
				if (*p1_v < *p2_v) {
					if (p1_sub)
						p1_sub = FALSE;
					p1_nv--;
					p1_v++;
				}
				else if (*p2_v < *p1_v) {
					if (p2_sub)
						p2_sub = FALSE;
					p2_nv--;
					p2_v++;
				}
				else {
					/* Equality, both next verts. */
					p1_nv--;
					p2_nv--;
					p1_v++;
					p2_v++;
				}
			}
			if (p1_nv && p1_sub)
				p1_sub = FALSE;
			else if (p2_nv && p2_sub)
				p2_sub = FALSE;

			if (p1_sub && p2_sub) {
				PRINT("\tPolys %u and %u use same vertices, considering poly %u as invalid.\n",
				      prev_sp->index, sp->index, sp->index);
				sp->invalid = TRUE;
			}
			/* XXX In fact, these might be valid? :/ */
			else if (p1_sub) {
				PRINT("\t%u is a sub-poly of %u, considering it as invalid.\n", sp->index, prev_sp->index);
				sp->invalid = TRUE;
			}
			else if (p2_sub) {
				PRINT("\t%u is a sub-poly of %u, considering it as invalid.\n", prev_sp->index, sp->index);
				prev_sp->invalid = TRUE;
				prev_sp = sp; /* sp is new reference poly. */
			}
#else
			if (0) {
				p1_sub += 0;
				p2_sub += 0;
			}
			if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
				if (do_verbose) {
					PRINT_ERR("\tPolys %u and %u use same vertices (%u",
					          prev_sp->index, sp->index, *p1_v);
					for (j = 1; j < p1_nv; j++)
						PRINT_ERR(", %u", p1_v[j]);
					PRINT_ERR("), considering poly %u as invalid.\n", sp->index);
				}
				else {
					is_valid = false;
				}
				sp->invalid = TRUE;
			}
#endif
			else {
				prev_sp = sp;
			}
		}

		/* Third check pass, testing loops used by none or more than one poly. */
		qsort(sort_polys, totpoly, sizeof(SortPoly), search_polyloop_cmp);
		sp = sort_polys;
		prev_sp = NULL;
		prev_end = 0;
		for (i = 0; i < totpoly; i++, sp++) {
			/* Free this now, we don't need it anymore, and avoid us another loop! */
			if (sp->verts)
				MEM_freeN(sp->verts);

			/* Note above prev_sp: in following code, we make sure it is always valid poly (or NULL). */
			if (sp->invalid) {
				if (do_fixes) {
					REMOVE_POLY_TAG((&mpolys[sp->index]));
					/* DO NOT REMOVE ITS LOOPS!!!
					 * As already invalid polys are at the end of the SortPoly list, the loops they
					 * were the only users have already been tagged as "to remove" during previous
					 * iterations, and we don't want to remove some loops that may be used by
					 * another valid poly! */
				}
			}
			/* Test loops users. */
			else {
				/* Unused loops. */
				if (prev_end < sp->loopstart) {
					for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) {
						PRINT_ERR("\tLoop %u is unused.\n", j);
						if (do_fixes)
							REMOVE_LOOP_TAG(ml);
					}
					prev_end = sp->loopstart + sp->numverts;
					prev_sp = sp;
				}
				/* Multi-used loops. */
				else if (prev_end > sp->loopstart) {
					PRINT_ERR("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n",
					          prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index);
					if (do_fixes) {
						REMOVE_POLY_TAG((&mpolys[sp->index]));
						/* DO NOT REMOVE ITS LOOPS!!!
						 * They might be used by some next, valid poly!
						 * Just not updating prev_end/prev_sp vars is enough to ensure the loops
						 * effectively no more needed will be marked as "to be removed"! */
					}
				}
				else {
					prev_end = sp->loopstart + sp->numverts;
					prev_sp = sp;
				}
			}
		}
		/* We may have some remaining unused loops to get rid of! */
		if (prev_end < totloop) {
			for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) {
				PRINT_ERR("\tLoop %u is unused.\n", j);
				if (do_fixes)
					REMOVE_LOOP_TAG(ml);
			}
		}

		MEM_freeN(sort_polys);
	}

	BLI_edgehash_free(edge_hash, NULL);

	/* fix deform verts */
	if (dverts) {
		MDeformVert *dv;
		for (i = 0, dv = dverts; i < totvert; i++, dv++) {
			MDeformWeight *dw;

			for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
				/* note, greater then max defgroups is accounted for in our code, but not < 0 */
				if (!finite(dw->weight)) {
					PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
					if (do_fixes) {
						dw->weight = 0.0f;
						vert_weights_fixed = TRUE;
					}
				}
				else if (dw->weight < 0.0f || dw->weight > 1.0f) {
					PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
					if (do_fixes) {
						CLAMP(dw->weight, 0.0f, 1.0f);
						vert_weights_fixed = TRUE;
					}
				}

				if (dw->def_nr < 0) {
					PRINT_ERR("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr);
					if (do_fixes) {
						defvert_remove_group(dv, dw);
						if (dv->dw) {
							/* re-allocated, the new values compensate for stepping
							 * within the for loop and may not be valid */
							j--;
							dw = dv->dw + j;

							vert_weights_fixed = TRUE;
						}
						else { /* all freed */
							break;
						}
					}
				}
			}
		}
	}

#   undef REMOVE_EDGE_TAG
#   undef IS_REMOVED_EDGE
#   undef REMOVE_LOOP_TAG
#   undef REMOVE_POLY_TAG

	if (mesh) {
		if (do_face_free) {
			BKE_mesh_strip_loose_faces(mesh);
		}

		if (do_polyloop_free) {
			BKE_mesh_strip_loose_polysloops(mesh);
		}

		if (do_edge_free) {
			BKE_mesh_strip_loose_edges(mesh);
		}

		if (do_edge_recalc) {
			BKE_mesh_calc_edges(mesh, true, false);
		}
	}

	if (mesh && mesh->mselect) {
		MSelect *msel;
		int free_msel = FALSE;

		for (i = 0, msel = mesh->mselect; i < mesh->totselect; i++, msel++) {
			int tot_elem = 0;

			if (msel->index < 0) {
				PRINT_ERR("\tMesh select element %d type %d index is negative, "
				          "resetting selection stack.\n", i, msel->type);
				free_msel = TRUE;
				break;
			}

			switch (msel->type) {
				case ME_VSEL:
					tot_elem = mesh->totvert;
					break;
				case ME_ESEL:
					tot_elem = mesh->totedge;
					break;
				case ME_FSEL:
					tot_elem = mesh->totface;
					break;
			}

			if (msel->index > tot_elem) {
				PRINT_ERR("\tMesh select element %d type %d index %d is larger than data array size %d, "
				          "resetting selection stack.\n", i, msel->type, msel->index, tot_elem);

				free_msel = TRUE;
				break;
			}
		}

		if (free_msel) {
			MEM_freeN(mesh->mselect);
			mesh->mselect = NULL;
			mesh->totselect = 0;
		}
	}

	PRINT_MSG("%s: finished\n\n", __func__);

	*r_change = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);

	return is_valid;
}
Exemplo n.º 20
0
/* Selects all visible keyframes in the same frames as the specified elements */
static void columnselect_graph_keys(bAnimContext *ac, short mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	Scene *scene = ac->scene;
	CfraElem *ce;
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked;
	
	/* initialize keyframe editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* build list of columns */
	switch (mode) {
		case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
			filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
			ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
			
			for (ale = anim_data.first; ale; ale = ale->next)
				ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
			
			ANIM_animdata_freelist(&anim_data);
			break;
			
		case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
			/* make a single CfraElem for storing this */
			ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
			BLI_addtail(&ked.list, ce);
			
			ce->cfra = (float)CFRA;
			break;
			
		case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
			ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
			break;
			
		default: /* invalid option */
			return;
	}
	
	/* set up BezTriple edit callbacks */
	select_cb = ANIM_editkeyframes_select(SELECT_ADD);
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
	
	/* loop through all of the keys and select additional keyframes
	 * based on the keys found to be selected above
	 */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* loop over cfraelems (stored in the KeyframeEditData->list)
		 *	- we need to do this here, as we can apply fewer NLA-mapping conversions
		 */
		for (ce = ked.list.first; ce; ce = ce->next) {
			/* set frame for validation callback to refer to */
			ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);

			/* select elements with frame number matching cfraelem */
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
		}
	}
	
	/* free elements */
	BLI_freelistN(&ked.list);
	ANIM_animdata_freelist(&anim_data);
}
Exemplo n.º 21
0
/* Setup motion paths for the given data
 * - Only used when explicitly calculating paths on bones which may/may not be consider already
 *
 * < scene: current scene (for frame ranges, etc.)
 * < ob: object to add paths for (must be provided)
 * < pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed)
 */
bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Object *ob, bPoseChannel *pchan)
{
	bAnimVizSettings *avs;
	bMotionPath *mpath, **dst;
	
	/* sanity checks */
	if (ELEM(NULL, scene, ob))
		return NULL;
		
	/* get destination data */
	if (pchan) {
		/* paths for posechannel - assume that posechannel belongs to the object */
		avs = &ob->pose->avs;
		dst = &pchan->mpath;
	}
	else {
		/* paths for object */
		avs = &ob->avs;
		dst = &ob->mpath;
	}

	/* avoid 0 size allocs */
	if (avs->path_sf >= avs->path_ef) {
		BKE_reportf(reports, RPT_ERROR,
		            "Motion Path frame extents invalid for %s (%d to %d).%s\n",
		            (pchan) ? pchan->name : ob->id.name,
		            avs->path_sf, avs->path_ef,
		            (avs->path_sf == avs->path_ef) ? " Cannot have single-frame paths." : "");
		return NULL;
	}

	/* if there is already a motionpath, just return that,
	 * provided it's settings are ok (saves extra free+alloc)
	 */
	if (*dst != NULL) {
		int expected_length = avs->path_ef - avs->path_sf;
		
		mpath = *dst;
		
		/* path is "valid" if length is valid, but must also be of the same length as is being requested */
		if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) {
			/* outer check ensures that we have some curve data for this path */
			if (mpath->length == expected_length) {
				/* return/use this as it is already valid length */
				return mpath;
			}
			else {
				/* clear the existing path (as the range has changed), and reallocate below */
				animviz_free_motionpath_cache(mpath);
			}
		}
	}
	else {
		/* create a new motionpath, and assign it */
		mpath = MEM_callocN(sizeof(bMotionPath), "bMotionPath");
		*dst = mpath;
	}
	
	/* set settings from the viz settings */
	mpath->start_frame = avs->path_sf;
	mpath->end_frame = avs->path_ef;
	
	mpath->length = mpath->end_frame - mpath->start_frame;
	
	if (avs->path_bakeflag & MOTIONPATH_BAKE_HEADS)
		mpath->flag |= MOTIONPATH_FLAG_BHEAD;
	else
		mpath->flag &= ~MOTIONPATH_FLAG_BHEAD;
	
	/* allocate a cache */
	mpath->points = MEM_callocN(sizeof(bMotionPathVert) * mpath->length, "bMotionPathVerts");
	
	/* tag viz settings as currently having some path(s) which use it */
	avs->path_bakeflag |= MOTIONPATH_BAKE_HAS_PATHS;
	
	/* return it */
	return mpath;
}
Exemplo n.º 22
0
/* name can be a dynamic string */
void BKE_write_undo(bContext *C, const char *name)
{
    uintptr_t maxmem, totmem, memused;
    int nr, success;
    UndoElem *uel;

    if( (U.uiflag & USER_GLOBALUNDO)==0) return;
    if( U.undosteps==0) return;

    /* remove all undos after (also when curundo==NULL) */
    while(undobase.last != curundo) {
        uel= undobase.last;
        BLI_remlink(&undobase, uel);
        BLO_free_memfile(&uel->memfile);
        MEM_freeN(uel);
    }

    /* make new */
    curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file");
    strncpy(uel->name, name, MAXUNDONAME-1);
    BLI_addtail(&undobase, uel);

    /* and limit amount to the maximum */
    nr= 0;
    uel= undobase.last;
    while(uel) {
        nr++;
        if(nr==U.undosteps) break;
        uel= uel->prev;
    }
    if(uel) {
        while(undobase.first!=uel) {
            UndoElem *first= undobase.first;
            BLI_remlink(&undobase, first);
            /* the merge is because of compression */
            BLO_merge_memfile(&first->memfile, &first->next->memfile);
            MEM_freeN(first);
        }
    }


    /* disk save version */
    if(UNDO_DISK) {
        static int counter= 0;
        char filepath[FILE_MAXDIR+FILE_MAXFILE];
        char numstr[32];
        int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */

        /* calculate current filepath */
        counter++;
        counter= counter % U.undosteps;

        BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
        BLI_make_file_string("/", filepath, btempdir, numstr);

        success= BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);

        BLI_strncpy(curundo->str, filepath, sizeof(curundo->str));
    }
    else {
        MemFile *prevfile=NULL;

        if(curundo->prev) prevfile= &(curundo->prev->memfile);

        memused= MEM_get_memory_in_use();
        success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags);
        curundo->undosize= MEM_get_memory_in_use() - memused;
    }

    if(U.undomemory != 0) {
        /* limit to maximum memory (afterwards, we can't know in advance) */
        totmem= 0;
        maxmem= ((uintptr_t)U.undomemory)*1024*1024;

        /* keep at least two (original + other) */
        uel= undobase.last;
        while(uel && uel->prev) {
            totmem+= uel->undosize;
            if(totmem>maxmem) break;
            uel= uel->prev;
        }

        if(uel) {
            if(uel->prev && uel->prev->prev)
                uel= uel->prev;

            while(undobase.first!=uel) {
                UndoElem *first= undobase.first;
                BLI_remlink(&undobase, first);
                /* the merge is because of compression */
                BLO_merge_memfile(&first->memfile, &first->next->memfile);
                MEM_freeN(first);
            }
        }
    }
}
Exemplo n.º 23
0
BMBVHTree *BKE_bmbvh_new(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free)
{
	/* could become argument */
	const float epsilon = FLT_EPSILON * 2.0f;

	struct BMLoop *(*looptris)[3] = em->looptris;
	BMBVHTree *bmtree = MEM_callocN(sizeof(*bmtree), "BMBVHTree");
	float cos[3][3];
	int i;
	int tottri;

	/* BKE_editmesh_tessface_calc() must be called already */
	BLI_assert(em->tottri != 0 || em->bm->totface == 0);

	if (cos_cage) {
		BM_mesh_elem_index_ensure(em->bm, BM_VERT);
	}

	bmtree->em = em;
	bmtree->bm = em->bm;
	bmtree->cos_cage = cos_cage;
	bmtree->cos_cage_free = cos_cage_free;
	bmtree->flag = flag;

	if (flag & (BMBVH_RESPECT_SELECT)) {
		tottri = 0;
		for (i = 0; i < em->tottri; i++) {
			if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
				tottri++;
			}
		}
	}
	else if (flag & (BMBVH_RESPECT_HIDDEN)) {
		tottri = 0;
		for (i = 0; i < em->tottri; i++) {
			if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
				tottri++;
			}
		}
	}
	else {
		tottri = em->tottri;
	}

	bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8);

	for (i = 0; i < em->tottri; i++) {

		if (flag & BMBVH_RESPECT_SELECT) {
			/* note, the arrays wont align now! take care */
			if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_SELECT)) {
				continue;
			}
		}
		else if (flag & BMBVH_RESPECT_HIDDEN) {
			/* note, the arrays wont align now! take care */
			if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
				continue;
			}
		}

		if (cos_cage) {
			copy_v3_v3(cos[0], cos_cage[BM_elem_index_get(looptris[i][0]->v)]);
			copy_v3_v3(cos[1], cos_cage[BM_elem_index_get(looptris[i][1]->v)]);
			copy_v3_v3(cos[2], cos_cage[BM_elem_index_get(looptris[i][2]->v)]);
		}
		else {
			copy_v3_v3(cos[0], looptris[i][0]->v->co);
			copy_v3_v3(cos[1], looptris[i][1]->v->co);
			copy_v3_v3(cos[2], looptris[i][2]->v->co);
		}

		BLI_bvhtree_insert(bmtree->tree, i, (float *)cos, 3);
	}
	
	BLI_bvhtree_balance(bmtree->tree);
	
	return bmtree;
}
Exemplo n.º 24
0
/* reading without uifont will create one */
void uiStyleInit(void)
{
  uiFont *font;
  uiStyle *style = U.uistyles.first;
  int monofont_size = datatoc_bmonofont_ttf_size;
  uchar *monofont_ttf = (uchar *)datatoc_bmonofont_ttf;

  /* recover from uninitialized dpi */
  if (U.dpi == 0) {
    U.dpi = 72;
  }
  CLAMP(U.dpi, 48, 144);

  for (font = U.uifonts.first; font; font = font->next) {
    BLF_unload_id(font->blf_id);
  }

  if (blf_mono_font != -1) {
    BLF_unload_id(blf_mono_font);
    blf_mono_font = -1;
  }

  if (blf_mono_font_render != -1) {
    BLF_unload_id(blf_mono_font_render);
    blf_mono_font_render = -1;
  }

  font = U.uifonts.first;

  /* default builtin */
  if (font == NULL) {
    font = MEM_callocN(sizeof(uiFont), "ui font");
    BLI_addtail(&U.uifonts, font);
  }

  if (U.font_path_ui[0]) {
    BLI_strncpy(font->filename, U.font_path_ui, sizeof(font->filename));
    font->uifont_id = UIFONT_CUSTOM1;
  }
  else {
    BLI_strncpy(font->filename, "default", sizeof(font->filename));
    font->uifont_id = UIFONT_DEFAULT;
  }

  for (font = U.uifonts.first; font; font = font->next) {

    if (font->uifont_id == UIFONT_DEFAULT) {
#ifdef WITH_INTERNATIONAL
      int font_size = datatoc_bfont_ttf_size;
      uchar *font_ttf = (uchar *)datatoc_bfont_ttf;
      static int last_font_size = 0;

      /* use unicode font for translation */
      if (U.transopts & USER_DOTRANSLATE) {
        font_ttf = BLF_get_unifont(&font_size);

        if (!font_ttf) {
          /* fall back if not found */
          font_size = datatoc_bfont_ttf_size;
          font_ttf = (uchar *)datatoc_bfont_ttf;
        }
      }

      /* relload only if needed */
      if (last_font_size != font_size) {
        BLF_unload("default");
        last_font_size = font_size;
      }

      font->blf_id = BLF_load_mem("default", font_ttf, font_size);
#else
      font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
#endif
    }
    else {
      font->blf_id = BLF_load(font->filename);
      if (font->blf_id == -1) {
        font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
      }
    }

    BLF_default_set(font->blf_id);

    if (font->blf_id == -1) {
      if (G.debug & G_DEBUG) {
        printf("%s: error, no fonts available\n", __func__);
      }
    }
    else {
      /* ? just for speed to initialize?
       * Yes, this build the glyph cache and create
       * the texture.
       */
      BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
      BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
      BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
    }
  }

  if (style == NULL) {
    ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
  }

#ifdef WITH_INTERNATIONAL
  /* use unicode font for text editor and interactive console */
  if (U.transopts & USER_DOTRANSLATE) {
    monofont_ttf = BLF_get_unifont_mono(&monofont_size);

    if (!monofont_ttf) {
      /* fall back if not found */
      monofont_size = datatoc_bmonofont_ttf_size;
      monofont_ttf = (uchar *)datatoc_bmonofont_ttf;
    }
  }
#endif

  /* XXX, this should be moved into a style,
   * but for now best only load the monospaced font once. */
  BLI_assert(blf_mono_font == -1);
  if (U.font_path_ui_mono[0]) {
    blf_mono_font = BLF_load_unique(U.font_path_ui_mono);
  }
  if (blf_mono_font == -1) {
    blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
  }

  BLF_size(blf_mono_font, 12 * U.pixelsize, 72);

  /* Set default flags based on UI preferences (not render fonts) */
  {
    int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT | BLF_HINTING_FULL);
    int flag_enable = 0;

    if (U.text_render & USER_TEXT_HINTING_NONE) {
      flag_enable |= BLF_HINTING_NONE;
    }
    else if (U.text_render & USER_TEXT_HINTING_SLIGHT) {
      flag_enable |= BLF_HINTING_SLIGHT;
    }
    else if (U.text_render & USER_TEXT_HINTING_FULL) {
      flag_enable |= BLF_HINTING_FULL;
    }

    if (U.text_render & USER_TEXT_DISABLE_AA) {
      flag_enable |= BLF_MONOCHROME;
    }

    for (font = U.uifonts.first; font; font = font->next) {
      if (font->blf_id != -1) {
        BLF_disable(font->blf_id, flag_disable);
        BLF_enable(font->blf_id, flag_enable);
      }
    }
    if (blf_mono_font != -1) {
      BLF_disable(blf_mono_font, flag_disable);
      BLF_enable(blf_mono_font, flag_enable);
    }
  }

  /**
   * Second for rendering else we get threading problems,
   *
   * \note This isn't good that the render font depends on the preferences,
   * keep for now though, since without this there is no way to display many unicode chars.
   */
  if (blf_mono_font_render == -1) {
    blf_mono_font_render = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
  }

  BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
}
Exemplo n.º 25
0
void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset, int slope)
{
	if(cuma->curve)
		MEM_freeN(cuma->curve);

	switch(preset) {
		case CURVE_PRESET_LINE: cuma->totpoint= 2; break;
		case CURVE_PRESET_SHARP: cuma->totpoint= 4; break;
		case CURVE_PRESET_SMOOTH: cuma->totpoint= 4; break;
		case CURVE_PRESET_MAX: cuma->totpoint= 2; break;
		case CURVE_PRESET_MID9: cuma->totpoint= 9; break;
		case CURVE_PRESET_ROUND: cuma->totpoint= 4; break;
		case CURVE_PRESET_ROOT: cuma->totpoint= 4; break;
	}

	cuma->curve= MEM_callocN(cuma->totpoint*sizeof(CurveMapPoint), "curve points");

	switch(preset) {
		case CURVE_PRESET_LINE:
			cuma->curve[0].x= clipr->xmin;
			cuma->curve[0].y= clipr->ymax;
			cuma->curve[0].flag= 0;
			cuma->curve[1].x= clipr->xmax;
			cuma->curve[1].y= clipr->ymin;
			cuma->curve[1].flag= 0;
			break;
		case CURVE_PRESET_SHARP:
			cuma->curve[0].x= 0;
			cuma->curve[0].y= 1;
			cuma->curve[1].x= 0.25;
			cuma->curve[1].y= 0.50;
			cuma->curve[2].x= 0.75;
			cuma->curve[2].y= 0.04;
			cuma->curve[3].x= 1;
			cuma->curve[3].y= 0;
			break;
		case CURVE_PRESET_SMOOTH:
			cuma->curve[0].x= 0;
			cuma->curve[0].y= 1;
			cuma->curve[1].x= 0.25;
			cuma->curve[1].y= 0.94;
			cuma->curve[2].x= 0.75;
			cuma->curve[2].y= 0.06;
			cuma->curve[3].x= 1;
			cuma->curve[3].y= 0;
			break;
		case CURVE_PRESET_MAX:
			cuma->curve[0].x= 0;
			cuma->curve[0].y= 1;
			cuma->curve[1].x= 1;
			cuma->curve[1].y= 1;
			break;
		case CURVE_PRESET_MID9:
			{
				int i;
				for (i=0; i < cuma->totpoint; i++)
				{
					cuma->curve[i].x= i / ((float)cuma->totpoint-1);
					cuma->curve[i].y= 0.5;
				}
			}
			break;
		case CURVE_PRESET_ROUND:
			cuma->curve[0].x= 0;
			cuma->curve[0].y= 1;
			cuma->curve[1].x= 0.5;
			cuma->curve[1].y= 0.90;
			cuma->curve[2].x= 0.86;
			cuma->curve[2].y= 0.5;
			cuma->curve[3].x= 1;
			cuma->curve[3].y= 0;
			break;
		case CURVE_PRESET_ROOT:
			cuma->curve[0].x= 0;
			cuma->curve[0].y= 1;
			cuma->curve[1].x= 0.25;
			cuma->curve[1].y= 0.95;
			cuma->curve[2].x= 0.75;
			cuma->curve[2].y= 0.44;
			cuma->curve[3].x= 1;
			cuma->curve[3].y= 0;
			break;
	}

	/* mirror curve in x direction to have positive slope
	 * rather than default negative slope */
	if (slope == CURVEMAP_SLOPE_POSITIVE) {
		int i, last=cuma->totpoint-1;
		CurveMapPoint *newpoints= MEM_dupallocN(cuma->curve);
		
		for (i=0; i<cuma->totpoint; i++) {
			newpoints[i].y = cuma->curve[last-i].y;
		}
		
		MEM_freeN(cuma->curve);
		cuma->curve = newpoints;
	}
	
	if(cuma->table) {
		MEM_freeN(cuma->table);
		cuma->table= NULL;
	}
}
Exemplo n.º 26
0
int WM_init_game(bContext *C)
{
	wmWindowManager *wm= CTX_wm_manager(C);
	wmWindow* win;

	ScrArea *sa;
	ARegion *ar= NULL;

	Scene *scene= CTX_data_scene(C);

	if (!scene) {
		// XXX, this should not be needed.
		Main *bmain = CTX_data_main(C);
		scene= bmain->scene.first;
	}

	win = wm->windows.first;

	//first to get a valid window
	if(win)
		CTX_wm_window_set(C, win);

	sa = biggest_view3d(C);
	ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);

	// if we have a valid 3D view
	if (sa && ar) {
		ARegion *arhide;

		CTX_wm_area_set(C, sa);
		CTX_wm_region_set(C, ar);

		/* disable quad view */
		if(ar->alignment == RGN_ALIGN_QSPLIT)
			WM_operator_name_call(C, "SCREEN_OT_region_quadview", WM_OP_EXEC_DEFAULT, NULL);

		/* toolbox, properties panel and header are hidden */
		for(arhide=sa->regionbase.first; arhide; arhide=arhide->next) {
			if(arhide->regiontype != RGN_TYPE_WINDOW) {
				if(!(arhide->flag & RGN_FLAG_HIDDEN)) {
					ED_region_toggle_hidden(C, arhide);
				}
			}
		}

		/* full screen the area */
		if(!sa->full) {
			ED_screen_full_toggle(C, win, sa);
		}

		/* Fullscreen */
		if(scene->gm.fullscreen) {
			WM_operator_name_call(C, "WM_OT_window_fullscreen_toggle", WM_OP_EXEC_DEFAULT, NULL);
			wm_get_screensize(&ar->winrct.xmax, &ar->winrct.ymax);
			ar->winx = ar->winrct.xmax + 1;
			ar->winy = ar->winrct.ymax + 1;
		}
		else
		{
			GHOST_RectangleHandle rect = GHOST_GetClientBounds(win->ghostwin);
			ar->winrct.ymax = GHOST_GetHeightRectangle(rect);
			ar->winrct.xmax = GHOST_GetWidthRectangle(rect);
			ar->winx = ar->winrct.xmax + 1;
			ar->winy = ar->winrct.ymax + 1;
			GHOST_DisposeRectangle(rect);
		}

		WM_operator_name_call(C, "VIEW3D_OT_game_start", WM_OP_EXEC_DEFAULT, NULL);

		return 1;
	}
	else
	{
		ReportTimerInfo *rti;

		BKE_report(&wm->reports, RPT_ERROR, "No valid 3D View found. Game auto start is not possible.");

		/* After adding the report to the global list, reset the report timer. */
		WM_event_remove_timer(wm, NULL, wm->reports.reporttimer);

		/* Records time since last report was added */
		wm->reports.reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER, 0.02);

		rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo");
		wm->reports.reporttimer->customdata = rti;
	}
	return 0;
}
Exemplo n.º 27
0
void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
{
	int x, y, c;
	unsigned int n, nl;
	double div, divl;
	float *rf=NULL;
	unsigned char *rc=NULL;
	unsigned int *bin_r, *bin_g, *bin_b, *bin_lum;
	int savedlines, saveline;
	float rgb[3], ycc[3], luma;
	int ycc_mode=-1;
	const short is_float = (ibuf->rect_float != NULL);

	if (ibuf->rect==NULL && ibuf->rect_float==NULL) return;

	if (scopes->ok == 1 ) return;

	if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f;

	/* hmmmm */
	if (!(ELEM(ibuf->channels, 3, 4))) return;

	scopes->hist.channels = 3;
	scopes->hist.x_resolution = 256;

	switch (scopes->wavefrm_mode) {
		case SCOPES_WAVEFRM_RGB:
			ycc_mode = -1;
			break;
		case SCOPES_WAVEFRM_LUMA:
		case SCOPES_WAVEFRM_YCC_JPEG:
			ycc_mode = BLI_YCC_JFIF_0_255;
			break;
		case SCOPES_WAVEFRM_YCC_601:
			ycc_mode = BLI_YCC_ITU_BT601;
			break;
		case SCOPES_WAVEFRM_YCC_709:
			ycc_mode = BLI_YCC_ITU_BT709;
			break;
	}

	/* temp table to count pix value for histo */
	bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");

	/* convert to number of lines with logarithmic scale */
	scopes->sample_lines = (scopes->accuracy*0.01f) * (scopes->accuracy*0.01f) * ibuf->y;
	
	if (scopes->sample_full)
		scopes->sample_lines = ibuf->y;

	/* scan the image */
	savedlines=0;
	for (c=0; c<3; c++) {
		scopes->minmax[c][0]=25500.0f;
		scopes->minmax[c][1]=-25500.0f;
	}
	
	scopes->waveform_tot = ibuf->x*scopes->sample_lines;
	
	if (scopes->waveform_1)
		MEM_freeN(scopes->waveform_1);
	if (scopes->waveform_2)
		MEM_freeN(scopes->waveform_2);
	if (scopes->waveform_3)
		MEM_freeN(scopes->waveform_3);
	if (scopes->vecscope)
		MEM_freeN(scopes->vecscope);
	
	scopes->waveform_1= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1");
	scopes->waveform_2= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2");
	scopes->waveform_3= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
	scopes->vecscope= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
	
	if (is_float)
		rf = ibuf->rect_float;
	else
		rc = (unsigned char *)ibuf->rect;

	for (y = 0; y < ibuf->y; y++) {
		if (savedlines<scopes->sample_lines && y>=((savedlines)*ibuf->y)/(scopes->sample_lines+1)) {
			saveline=1;
		} else saveline=0;
		for (x = 0; x < ibuf->x; x++) {

			if (is_float) {
				if (use_color_management)
					linearrgb_to_srgb_v3_v3(rgb, rf);
				else
					copy_v3_v3(rgb, rf);
			}
			else {
				for (c=0; c<3; c++)
					rgb[c] = rc[c] * INV_255;
			}

			/* we still need luma for histogram */
			luma = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];

			/* check for min max */
			if(ycc_mode == -1 ) {
				for (c=0; c<3; c++) {
					if (rgb[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgb[c];
					if (rgb[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgb[c];
				}
			}
			else {
				rgb_to_ycc(rgb[0],rgb[1],rgb[2],&ycc[0],&ycc[1],&ycc[2], ycc_mode);
				for (c=0; c<3; c++) {
					ycc[c] *=INV_255;
					if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c];
					if (ycc[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = ycc[c];
				}
			}
			/* increment count for histo*/
			bin_r[ get_bin_float(rgb[0]) ] += 1;
			bin_g[ get_bin_float(rgb[1]) ] += 1;
			bin_b[ get_bin_float(rgb[2]) ] += 1;
			bin_lum[ get_bin_float(luma) ] += 1;

			/* save sample if needed */
			if(saveline) {
				const float fx = (float)x / (float)ibuf->x;
				const int idx = 2*(ibuf->x*savedlines+x);
				save_sample_line(scopes, idx, fx, rgb, ycc);
			}

			rf+= ibuf->channels;
			rc+= ibuf->channels;
		}
		if (saveline)
			savedlines +=1;
	}

	/* convert hist data to float (proportional to max count) */
	n=0;
	nl=0;
	for (x=0; x<256; x++) {
		if (bin_r[x] > n)
			n = bin_r[x];
		if (bin_g[x] > n)
			n = bin_g[x];
		if (bin_b[x] > n)
			n = bin_b[x];
		if (bin_lum[x] > nl)
			nl = bin_lum[x];
	}
	div = 1.0/(double)n;
	divl = 1.0/(double)nl;
	for (x=0; x<256; x++) {
		scopes->hist.data_r[x] = bin_r[x] * div;
		scopes->hist.data_g[x] = bin_g[x] * div;
		scopes->hist.data_b[x] = bin_b[x] * div;
		scopes->hist.data_luma[x] = bin_lum[x] * divl;
	}
	MEM_freeN(bin_r);
	MEM_freeN(bin_g);
	MEM_freeN(bin_b);
	MEM_freeN(bin_lum);

	scopes->ok = 1;
}
Exemplo n.º 28
0
/* Simple Weighted Smoothing
 *
 * (average of surrounding verts)
 */
static void smooth_iter__simple(
    CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
    float (*vertexCos)[3], unsigned int numVerts,
    const float *smooth_weights,
    unsigned int iterations)
{
    const float lambda = csmd->lambda;
    unsigned int i;

    const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
    const MEdge *edges = dm->getEdgeArray(dm);
    float *vertex_edge_count_div;

    struct SmoothingData_Simple {
        float delta[3];
    } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__);

    vertex_edge_count_div = MEM_callocN((size_t)numVerts * sizeof(float), __func__);

    /* calculate as floats to avoid int->float conversion in #smooth_iter */
    for (i = 0; i < numEdges; i++) {
        vertex_edge_count_div[edges[i].v1] += 1.0f;
        vertex_edge_count_div[edges[i].v2] += 1.0f;
    }

    /* a little confusing, but we can include 'lambda' and smoothing weight
     * here to avoid multiplying for every iteration */
    if (smooth_weights == NULL) {
        for (i = 0; i < numVerts; i++) {
            vertex_edge_count_div[i] =
                lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f);
        }
    }
    else {
        for (i = 0; i < numVerts; i++) {
            vertex_edge_count_div[i] =
                smooth_weights[i] * lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f);
        }
    }

    /* -------------------------------------------------------------------- */
    /* Main Smoothing Loop */

    while (iterations--) {
        for (i = 0; i < numEdges; i++) {
            struct SmoothingData_Simple *sd_v1;
            struct SmoothingData_Simple *sd_v2;
            float edge_dir[3];

            sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]);

            sd_v1 = &smooth_data[edges[i].v1];
            sd_v2 = &smooth_data[edges[i].v2];

            add_v3_v3(sd_v1->delta, edge_dir);
            sub_v3_v3(sd_v2->delta, edge_dir);
        }


        for (i = 0; i < numVerts; i++) {
            struct SmoothingData_Simple *sd = &smooth_data[i];
            madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]);
            /* zero for the next iteration (saves memset on entire array) */
            memset(sd, 0, sizeof(*sd));
        }
    }

    MEM_freeN(vertex_edge_count_div);
    MEM_freeN(smooth_data);
}
Exemplo n.º 29
0
static void fcm_generator_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime)
{
	FMod_Generator *data= (FMod_Generator *)fcm->data;
	
	/* behavior depends on mode 
	 * NOTE: the data in its default state is fine too
	 */
	switch (data->mode) {
		case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
		{
			/* we overwrite cvalue with the sum of the polynomial */
			float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
			float value= 0.0f;
			unsigned int i;
			
			/* for each x^n, precalculate value based on previous one first... this should be 
			 * faster that calling pow() for each entry
			 */
			for (i=0; i < data->arraysize; i++) {
				/* first entry is x^0 = 1, otherwise, calculate based on previous */
				if (i)
					powers[i]= powers[i-1] * evaltime;
				else
					powers[0]= 1;
			}
			
			/* for each coefficient, add to value, which we'll write to *cvalue in one go */
			for (i=0; i < data->arraysize; i++)
				value += data->coefficients[i] * powers[i];
			
			/* only if something changed, write *cvalue in one go */
			if (data->poly_order) {
				if (data->flag & FCM_GENERATOR_ADDITIVE)
					*cvalue += value;
				else
					*cvalue= value;
			}
				
			/* cleanup */
			if (powers) 
				MEM_freeN(powers);
		}
			break;
			
		case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial */
		{
			float value= 1.0f, *cp=NULL;
			unsigned int i;
			
			/* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
			for (cp=data->coefficients, i=0; (cp) && (i < (unsigned int)data->poly_order); cp+=2, i++) 
				value *= (cp[0]*evaltime + cp[1]);
				
			/* only if something changed, write *cvalue in one go */
			if (data->poly_order) {
				if (data->flag & FCM_GENERATOR_ADDITIVE)
					*cvalue += value;
				else
					*cvalue= value;
			}
		}
			break;
	}
}
Exemplo n.º 30
0
Arquivo: smoke.c Projeto: jinjoh/NOOR
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);
}