Beispiel #1
0
void initElbeemMesh(struct Scene *scene, struct Object *ob,
			int *numVertices, float **vertices,
	  int *numTriangles, int **triangles,
	  int useGlobalCoords, int modifierIndex)
{
	DerivedMesh *dm = NULL;
	MVert *mvert;
	MFace *mface;
	int countTris=0, i, totvert, totface;
	float *verts;
	int *tris;

	dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);
	//dm = mesh_create_derived_no_deform(ob,NULL);

	mvert = dm->getVertArray(dm);
	mface = dm->getFaceArray(dm);
	totvert = dm->getNumVerts(dm);
	totface = dm->getNumFaces(dm);

	*numVertices = totvert;
	verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
	for(i=0; i<totvert; i++) {
		VECCOPY( &verts[i*3], mvert[i].co);
		if(useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i*3]); }
	}
	*vertices = verts;

	for(i=0; i<totface; i++) {
		countTris++;
		if(mface[i].v4) { countTris++; }
	}
	*numTriangles = countTris;
	tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
	countTris = 0;
	for(i=0; i<totface; i++) {
		int face[4];
		face[0] = mface[i].v1;
		face[1] = mface[i].v2;
		face[2] = mface[i].v3;
		face[3] = mface[i].v4;

		tris[countTris*3+0] = face[0];
		tris[countTris*3+1] = face[1];
		tris[countTris*3+2] = face[2];
		countTris++;
		if(face[3]) {
			tris[countTris*3+0] = face[0];
			tris[countTris*3+1] = face[2];
			tris[countTris*3+2] = face[3];
			countTris++;
		}
	}
	*triangles = tris;

	dm->release(dm);
}
static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						int UNUSED(useRenderParams),
						int UNUSED(isFinalCalc))
{
	DerivedMesh *dm = derivedData, *result;
	ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
	ParticleSimulationData sim;
	ParticleSystem *psys= NULL;
	ParticleData *pa= NULL, *pars= NULL;
	MFace *mface, *orig_mface;
	MVert *mvert, *orig_mvert;
	int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
	short track=ob->trackflag%3, trackneg, axis = pimd->axis;
	float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
	float *size=NULL;

	trackneg=((ob->trackflag>2)?1:0);

	if(pimd->ob==ob){
		pimd->ob= NULL;
		return derivedData;
	}

	if(pimd->ob){
		psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
		if(psys==NULL || psys->totpart==0)
			return derivedData;
	}
	else return derivedData;

	if(pimd->flag & eParticleInstanceFlag_Parents)
		totpart+=psys->totpart;
	if(pimd->flag & eParticleInstanceFlag_Children){
		if(totpart==0)
			first_particle=psys->totpart;
		totpart+=psys->totchild;
	}

	if(totpart==0)
		return derivedData;

	sim.scene = md->scene;
	sim.ob = pimd->ob;
	sim.psys = psys;
	sim.psmd = psys_get_modifier(pimd->ob, psys);

	if(pimd->flag & eParticleInstanceFlag_UseSize) {
		int p;
		float *si;
		si = size = MEM_callocN(totpart * sizeof(float), "particle size array");

		if(pimd->flag & eParticleInstanceFlag_Parents) {
			for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
				*si = pa->size;
		}

		if(pimd->flag & eParticleInstanceFlag_Children) {
			ChildParticle *cpa = psys->child;

			for(p=0; p<psys->totchild; p++, cpa++, si++) {
				*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
			}
		}
	}

	pars=psys->particles;

	totvert=dm->getNumVerts(dm);
	totface=dm->getNumFaces(dm);

	maxvert=totvert*totpart;
	maxface=totface*totpart;

	psys->lattice=psys_get_lattice(&sim);

	if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){

		float min_r[3], max_r[3];
		INIT_MINMAX(min_r, max_r);
		dm->getMinMax(dm, min_r, max_r);
		min_co=min_r[track];
		max_co=max_r[track];
	}

	result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);

	mvert=result->getVertArray(result);
	orig_mvert=dm->getVertArray(dm);

	for(i=0; i<maxvert; i++){
		MVert *inMV;
		MVert *mv = mvert + i;
		ParticleKey state;

		inMV = orig_mvert + i%totvert;
		DM_copy_vert_data(dm, result, i%totvert, i, 1);
		*mv = *inMV;

		/*change orientation based on object trackflag*/
		copy_v3_v3(temp_co, mv->co);
		mv->co[axis]=temp_co[track];
		mv->co[(axis+1)%3]=temp_co[(track+1)%3];
		mv->co[(axis+2)%3]=temp_co[(track+2)%3];

		if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
			float ran = 0.0f;
			if(pimd->random_position != 0.0f) {
				BLI_srandom(psys->seed + (i/totvert)%totpart);
				ran = pimd->random_position * BLI_frand();
			}

			if(pimd->flag & eParticleInstanceFlag_KeepShape) {
				state.time = pimd->position * (1.0f - ran);
			}
			else {
				state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);

				if(trackneg)
					state.time=1.0f-state.time;

				mv->co[axis] = 0.0;
			}

			psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);

			normalize_v3(state.vel);

			/* TODO: incremental rotations somehow */
			if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
				state.rot[0] = 1;
				state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
			}
			else {
				float temp[3] = {0.0f,0.0f,0.0f};
				temp[axis] = 1.0f;

				cross_v3_v3v3(cross, temp, state.vel);

				/* state.vel[axis] is the only component surviving from a dot product with the axis */
				axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
			}

		}
		else{
			state.time=-1.0;
			psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
		}

		mul_qt_v3(state.rot,mv->co);
		if(pimd->flag & eParticleInstanceFlag_UseSize)
			mul_v3_fl(mv->co, size[i/totvert]);
		VECADD(mv->co,mv->co,state.co);
	}

	mface=result->getFaceArray(result);
	orig_mface=dm->getFaceArray(dm);

	for(i=0; i<maxface; i++){
		MFace *inMF;
		MFace *mf = mface + i;

		if(pimd->flag & eParticleInstanceFlag_Parents){
			if(i/totface>=psys->totpart){
				if(psys->part->childtype==PART_CHILD_PARTICLES)
					pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
				else
					pa= NULL;
			}
			else
				pa=pars+i/totface;
		}
		else{
			if(psys->part->childtype==PART_CHILD_PARTICLES)
				pa=psys->particles+(psys->child+i/totface)->parent;
			else
				pa= NULL;
		}

		if(pa){
			if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
			if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
			if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
		}

		inMF = orig_mface + i%totface;
		DM_copy_face_data(dm, result, i%totface, i, 1);
		*mf = *inMF;

		mf->v1+=(i/totface)*totvert;
		mf->v2+=(i/totface)*totvert;
		mf->v3+=(i/totface)*totvert;
		if(mf->v4)
			mf->v4+=(i/totface)*totvert;
	}

	CDDM_calc_edges(result);
	CDDM_calc_normals(result);

	if(psys->lattice){
		end_latt_deform(psys->lattice);
		psys->lattice= NULL;
	}

	if(size)
		MEM_freeN(size);

	return result;
}
Beispiel #3
0
static DerivedMesh *fluidsim_read_cache(DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
{
	int displaymode = 0;
	int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */
	char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
	FluidsimSettings *fss = fluidmd->fss;
	DerivedMesh *dm = NULL;
	MFace *mface;
	int numfaces;
	int mat_nr, flag, i;

	if(!useRenderParams) {
		displaymode = fss->guiDisplayMode;
	} else {
		displaymode = fss->renderDisplayMode;
	}

	BLI_strncpy(targetDir, fss->surfdataPath, sizeof(targetDir));

	// use preview or final mesh?
	if(displaymode==1)
	{
		// just display original object
		return NULL;
	}
	else if(displaymode==2)
	{
		strcat(targetDir,"fluidsurface_preview_####");
	}
	else
	{ // 3
		strcat(targetDir,"fluidsurface_final_####");
	}

	BLI_path_abs(targetDir, G.main->name);
	BLI_path_frame(targetDir, curFrame, 0); // fixed #frame-no

	BLI_snprintf(targetFile, sizeof(targetFile), "%s.bobj.gz", targetDir);

	dm = fluidsim_read_obj(targetFile);

	if(!dm)
	{
		// switch, abort background rendering when fluidsim mesh is missing
		const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp

		if(G.background==1) {
			if(getenv(strEnvName2)) {
				int elevel = atoi(getenv(strEnvName2));
				if(elevel>0) {
					printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
					exit(1);
				}
			}
		}

		// display org. object upon failure which is in dm
		return NULL;
	}

	// assign material + flags to new dm
	mface = orgdm->getFaceArray(orgdm);
	mat_nr = mface[0].mat_nr;
	flag = mface[0].flag;

	mface = dm->getFaceArray(dm);
	numfaces = dm->getNumFaces(dm);
	for(i=0; i<numfaces; i++)
	{
		mface[i].mat_nr = mat_nr;
		mface[i].flag = flag;
	}

	// load vertex velocities, if they exist...
	// TODO? use generate flag as loading flag as well?
	// warning, needs original .bobj.gz mesh loading filename
	if(displaymode==3)
	{
		fluidsim_read_vel_cache(fluidmd, dm, targetFile);
	}
	else
	{
		if(fss->meshVelocities)
			MEM_freeN(fss->meshVelocities);

		fss->meshVelocities = NULL;
	}

	return dm;
}
Beispiel #4
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  int useRenderParams,
                                  int UNUSED(isFinalCalc))
{
    DerivedMesh *dm= derivedData;
    DerivedMesh *result;
    ScrewModifierData *ltmd= (ScrewModifierData*) md;

    int *origindex;
    int mface_index=0;
    int step;
    int i, j;
    int i1,i2;
    int step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps;
    const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
    int maxVerts=0, maxEdges=0, maxFaces=0;
    int totvert= dm->getNumVerts(dm);
    int totedge= dm->getNumEdges(dm);

    char axis_char= 'X', close;
    float angle= ltmd->angle;
    float screw_ofs= ltmd->screw_ofs;
    float axis_vec[3]= {0.0f, 0.0f, 0.0f};
    float tmp_vec1[3], tmp_vec2[3];
    float mat3[3][3];
    float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
    float mtx_tx_inv[4][4]; /* inverted */
    float mtx_tmp_a[4][4];

    int vc_tot_linked= 0;
    short other_axis_1, other_axis_2;
    float *tmpf1, *tmpf2;

    MFace *mface_new, *mf_new;
    MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
    MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;

    ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;

    /* dont do anything? */
    if (!totvert)
        return CDDM_from_template(dm, 0, 0, 0);

    switch(ltmd->axis) {
    case 0:
        other_axis_1=1;
        other_axis_2=2;
        break;
    case 1:
        other_axis_1=0;
        other_axis_2=2;
        break;
    default: /* 2, use default to quiet warnings */
        other_axis_1=0;
        other_axis_2=1;
        break;
    }

    axis_vec[ltmd->axis]= 1.0f;

    if (ltmd->ob_axis) {
        /* calc the matrix relative to the axis object */
        invert_m4_m4(mtx_tmp_a, ob->obmat);
        copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
        mul_m4_m4m4(mtx_tx, mtx_tx_inv, mtx_tmp_a);

        /* calc the axis vec */
        mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
        normalize_v3(axis_vec);

        /* screw */
        if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
            /* find the offset along this axis relative to this objects matrix */
            float totlen = len_v3(mtx_tx[3]);

            if(totlen != 0.0f) {
                float zero[3]= {0.0f, 0.0f, 0.0f};
                float cp[3];
                screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
            }
            else {
                screw_ofs= 0.0f;
            }
        }

        /* angle */

#if 0	// cant incluide this, not predictable enough, though quite fun,.
        if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
            float mtx3_tx[3][3];
            copy_m3_m4(mtx3_tx, mtx_tx);

            float vec[3] = {0,1,0};
            float cross1[3];
            float cross2[3];
            cross_v3_v3v3(cross1, vec, axis_vec);

            mul_v3_m3v3(cross2, mtx3_tx, cross1);
            {
                float c1[3];
                float c2[3];
                float axis_tmp[3];

                cross_v3_v3v3(c1, cross2, axis_vec);
                cross_v3_v3v3(c2, axis_vec, c1);


                angle= angle_v3v3(cross1, c2);

                cross_v3_v3v3(axis_tmp, cross1, c2);
                normalize_v3(axis_tmp);

                if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
                    angle= -angle;

            }
        }
#endif
    }
    else {
        /* exis char is used by i_rotate*/
        axis_char += ltmd->axis; /* 'X' + axis */

        /* useful to be able to use the axis vec in some cases still */
        zero_v3(axis_vec);
        axis_vec[ltmd->axis]= 1.0f;
    }

    /* apply the multiplier */
    angle *= ltmd->iter;
    screw_ofs *= ltmd->iter;

    /* multiplying the steps is a bit tricky, this works best */
    step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);

    /* will the screw be closed?
     * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */
    if (fabsf(screw_ofs) <= (FLT_EPSILON*100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON*100.0f)) {
        close= 1;
        step_tot--;
        if(step_tot < 3) step_tot= 3;

        maxVerts =	totvert  * step_tot; /* -1 because we're joining back up */
        maxEdges =	(totvert * step_tot) + /* these are the edges between new verts */
                    (totedge * step_tot); /* -1 because vert edges join */
        maxFaces =	totedge * step_tot;

        screw_ofs= 0.0f;
    }
    else {
        close= 0;
        if(step_tot < 3) step_tot= 3;

        maxVerts =	totvert  * step_tot; /* -1 because we're joining back up */
        maxEdges =	(totvert * (step_tot-1)) + /* these are the edges between new verts */
                    (totedge * step_tot); /* -1 because vert edges join */
        maxFaces =	totedge * (step_tot-1);
    }

    result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);

    /* copy verts from mesh */
    mvert_orig =	dm->getVertArray(dm);
    medge_orig =	dm->getEdgeArray(dm);

    mvert_new =		result->getVertArray(result);
    mface_new =		result->getFaceArray(result);
    medge_new =		result->getEdgeArray(result);

    origindex= result->getFaceDataArray(result, CD_ORIGINDEX);

    DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */

    /* Set the locations of the first set of verts */

    mv_new= mvert_new;
    mv_orig= mvert_orig;

    /* Copy the first set of edges */
    med_orig= medge_orig;
    med_new= medge_new;
    for (i=0; i < totedge; i++, med_orig++, med_new++) {
        med_new->v1= med_orig->v1;
        med_new->v2= med_orig->v2;
        med_new->crease= med_orig->crease;
        med_new->flag= med_orig->flag &  ~ME_LOOSEEDGE;
    }

    if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
        /*
         * Normal Calculation (for face flipping)
         * Sort edge verts for correct face flipping
         * NOT REALLY NEEDED but face flipping is nice.
         *
         * */


        /* Notice!
         *
         * Since we are only ordering the edges here it can avoid mallocing the
         * extra space by abusing the vert array berfore its filled with new verts.
         * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
         * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
         * so its safe to use the second 2 thrids of MVert the array for vert_connect,
         * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
         * at the moment there is no chance of that being a problem,
         * unless MVert becomes half its current size.
         *
         * once the edges are ordered, vert_connect is not needed and it can be used for verts
         *
         * This makes the modifier faster with one less alloc.
         */

        vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
        //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
        vc= vert_connect;

        /* Copy Vert Locations */
        /* - We can do this in a later loop - only do here if no normal calc */
        if (!totedge) {
            for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
                copy_v3_v3(mv_new->co, mv_orig->co);
                normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is really a dummy normal */
            }
        }
        else {
            /*printf("\n\n\n\n\nStarting Modifier\n");*/
            /* set edge users */
            med_new= medge_new;
            mv_new= mvert_new;

            if (ltmd->ob_axis) {
                /*mtx_tx is initialized early on */
                for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
                    vc->co[0]= mv_new->co[0]= mv_orig->co[0];
                    vc->co[1]= mv_new->co[1]= mv_orig->co[1];
                    vc->co[2]= mv_new->co[2]= mv_orig->co[2];

                    vc->flag= 0;
                    vc->e[0]= vc->e[1]= NULL;
                    vc->v[0]= vc->v[1]= -1;

                    mul_m4_v3(mtx_tx, vc->co);
                    /* length in 2d, dont sqrt because this is only for comparison */
                    vc->dist =	vc->co[other_axis_1]*vc->co[other_axis_1] +
                                vc->co[other_axis_2]*vc->co[other_axis_2];

                    /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
                }
            }
            else {
                for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
                    vc->co[0]= mv_new->co[0]= mv_orig->co[0];
                    vc->co[1]= mv_new->co[1]= mv_orig->co[1];
                    vc->co[2]= mv_new->co[2]= mv_orig->co[2];

                    vc->flag= 0;
                    vc->e[0]= vc->e[1]= NULL;
                    vc->v[0]= vc->v[1]= -1;

                    /* length in 2d, dont sqrt because this is only for comparison */
                    vc->dist =	vc->co[other_axis_1]*vc->co[other_axis_1] +
                                vc->co[other_axis_2]*vc->co[other_axis_2];

                    /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
                }
            }

            /* this loop builds connectivity info for verts */
            for (i=0; i<totedge; i++, med_new++) {
                vc= &vert_connect[med_new->v1];

                if (vc->v[0] == -1) { /* unused */
                    vc->v[0]= med_new->v2;
                    vc->e[0]= med_new;
                }
                else if (vc->v[1] == -1) {
                    vc->v[1]= med_new->v2;
                    vc->e[1]= med_new;
                }
                else {
                    vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
                }

                vc= &vert_connect[med_new->v2];

                /* same as above but swap v1/2 */
                if (vc->v[0] == -1) { /* unused */
                    vc->v[0]= med_new->v1;
                    vc->e[0]= med_new;
                }
                else if (vc->v[1] == -1) {
                    vc->v[1]= med_new->v1;
                    vc->e[1]= med_new;
                }
                else {
                    vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
                }
            }

            /* find the first vert */
            vc= vert_connect;
            for (i=0; i < totvert; i++, vc++) {
                /* Now do search for connected verts, order all edges and flip them
                 * so resulting faces are flipped the right way */
                vc_tot_linked= 0; /* count the number of linked verts for this loop */
                if (vc->flag == 0) {
                    int v_best=-1, ed_loop_closed=0; /* vert and vert new */
                    ScrewVertIter lt_iter;
                    int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */
                    float fl= -1.0f;

                    /*printf("Loop on connected vert: %i\n", i);*/

                    for(j=0; j<2; j++) {
                        /*printf("\tSide: %i\n", j);*/
                        screwvert_iter_init(&lt_iter, vert_connect, i, j);
                        if (j == 1) {
                            screwvert_iter_step(&lt_iter);
                        }
                        while (lt_iter.v_poin) {
                            /*printf("\t\tVERT: %i\n", lt_iter.v);*/
                            if (lt_iter.v_poin->flag) {
                                /*printf("\t\t\tBreaking Found end\n");*/
                                //endpoints[0]= endpoints[1]= -1;
                                ed_loop_closed= 1; /* circle */
                                break;
                            }
                            lt_iter.v_poin->flag= 1;
                            vc_tot_linked++;
                            /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
                            if (fl <= lt_iter.v_poin->dist) {
                                fl= lt_iter.v_poin->dist;
                                v_best= lt_iter.v;
                                /*printf("\t\t\tVERT BEST: %i\n", v_best);*/
                            }
                            screwvert_iter_step(&lt_iter);
                            if (!lt_iter.v_poin) {
                                /*printf("\t\t\tFound End Also Num %i\n", j);*/
                                /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
                                break;
                            }
                        }
                    }

                    /* now we have a collection of used edges. flip their edges the right way*/
                    /*if (v_best != -1) - */

                    /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/

                    if (vc_tot_linked>1) {
                        float vf_1, vf_2, vf_best;

                        vc_tmp= &vert_connect[v_best];

                        tmpf1= vert_connect[vc_tmp->v[0]].co;
                        tmpf2= vert_connect[vc_tmp->v[1]].co;


                        /* edge connects on each side! */
                        if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
                            /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
                            /* find out which is higher */

                            vf_1= tmpf1[ltmd->axis];
                            vf_2= tmpf2[ltmd->axis];
                            vf_best= vc_tmp->co[ltmd->axis];

                            if (vf_1 < vf_best && vf_best < vf_2) {
                                ed_loop_flip= 0;
                            }
                            else if (vf_1 > vf_best && vf_best > vf_2) {
                                ed_loop_flip= 1;
                            }
                            else {
                                /* not so simple to work out which edge is higher */
                                sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
                                sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
                                normalize_v3(tmp_vec1);
                                normalize_v3(tmp_vec2);

                                if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
                                    ed_loop_flip= 1;
                                }
                                else {
                                    ed_loop_flip= 0;
                                }
                            }
                        }
                        else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
                            /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
                            if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
                                ed_loop_flip= 1;
                            }
                            else { /* best is below or even... in even case we cant know whet  to do. */
                                ed_loop_flip= 0;
                            }

                        }/* else {
							printf("No Connected ___\n");
						}*/

                        /*printf("flip direction %i\n", ed_loop_flip);*/


                        /* switch the flip option if set
                         * note: flip is now done at face level so copying vgroup slizes is easier */
                        /*
                        if (do_flip)
                        	ed_loop_flip= !ed_loop_flip;
                        */

                        if (angle < 0.0f)
                            ed_loop_flip= !ed_loop_flip;

                        /* if its closed, we only need 1 loop */
                        for(j=ed_loop_closed; j<2; j++) {
                            /*printf("Ordering Side J %i\n", j);*/

                            screwvert_iter_init(&lt_iter, vert_connect, v_best, j);
                            /*printf("\n\nStarting - Loop\n");*/
                            lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */


                            /* If this is the vert off the best vert and
                             * the best vert has 2 edges connected too it
                             * then swap the flip direction */
                            if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
                                ed_loop_flip= !ed_loop_flip;

                            while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
                                /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/

                                lt_iter.v_poin->flag= 2;
                                if (lt_iter.e) {
                                    if (lt_iter.v == lt_iter.e->v1) {
                                        if (ed_loop_flip == 0) {
                                            /*printf("\t\t\tFlipping 0\n");*/
                                            SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
                                        }/* else {
											printf("\t\t\tFlipping Not 0\n");
										}*/
                                    }
                                    else if (lt_iter.v == lt_iter.e->v2) {
                                        if (ed_loop_flip == 1) {
                                            /*printf("\t\t\tFlipping 1\n");*/
                                            SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
                                        }/* else {
											printf("\t\t\tFlipping Not 1\n");
										}*/
                                    }/* else {
										printf("\t\tIncorrect edge topology");
									}*/
                                }/* else {
									printf("\t\tNo Edge at this point\n");
								}*/
                                screwvert_iter_step(&lt_iter);
                            }
                        }
Beispiel #5
0
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated)
{
	Object *ob, *ob_iter;
	Base *base = NULL;
	DupliObject *dob;
	DerivedMesh *dm;
	Mesh *me= par->data;
	MTFace *mtface;
	MFace *mface;
	MVert *mvert;
	float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w;
	int lay, oblay, totface, a;
	Scene *sce = NULL;
	Group *group = NULL;
	GroupObject *go = NULL;
	EditMesh *em;
	float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
	
	/* simple preventing of too deep nested groups */
	if(level>MAX_DUPLI_RECUR) return;
	
	Mat4CpyMat4(pmat, par->obmat);
	
	em = BKE_mesh_get_editmesh(me);
	if(em) {
		int totvert;
		
		dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
		dm->copyFaceArray(dm, mface);
		totvert= dm->getNumVerts(dm);
		mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
		dm->copyVertArray(dm, mvert);

		BKE_mesh_end_editmesh(me, em);
	}
	else {
		dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= dm->getFaceArray(dm);
		mvert= dm->getVertArray(dm);
	}

	if(G.rendering) {

		orco= (float(*)[3])get_mesh_orco_verts(par);
		transform_mesh_orco_verts(me, orco, me->totvert, 0);
		mtface= me->mtface;
	}
	else {
		orco= NULL;
		mtface= NULL;
	}
	
	/* having to loop on scene OR group objects is NOT FUN */
	if (GS(id->name) == ID_SCE) {
		sce = (Scene *)id;
		lay= sce->lay;
		base= sce->base.first;
	} else {
		group = (Group *)id;
		lay= group->layer;
		go = group->gobject.first;
	}
	
	/* Start looping on Scene OR Group objects */
	while (base || go) { 
		if (sce) {
			ob_iter= base->object;
			oblay = base->lay;
		} else {
			ob_iter= go->ob;
			oblay = ob_iter->lay;
		}
		
		if (lay & oblay && scene->obedit!=ob_iter) {
			ob=ob_iter->parent;
			while(ob) {
				if(ob==par) {
					ob = ob_iter;
	/* End Scene/Group object loop, below is generic */
					
					/* par_space_mat - only used for groups so we can modify the space dupli's are in
					   when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
					*/
					if(par_space_mat)
						Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat);
					else
						Mat4CpyMat4(ob__obmat, ob->obmat);
					
					Mat3CpyMat4(imat, ob->parentinv);
						
					/* mballs have a different dupli handling */
					if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;	/* doesnt render */

					for(a=0; a<totface; a++) {
						int mv1 = mface[a].v1;
						int mv2 = mface[a].v2;
						int mv3 = mface[a].v3;
						int mv4 = mface[a].v4;
						float *v1= mvert[mv1].co;
						float *v2= mvert[mv2].co;
						float *v3= mvert[mv3].co;
						float *v4= (mv4)? mvert[mv4].co: NULL;
						float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];

						/* translation */
						if(v4)
							CalcCent4f(cent, v1, v2, v3, v4);
						else
							CalcCent3f(cent, v1, v2, v3);
						Mat4MulVecfl(pmat, cent);
						
						VecSubf(cent, cent, pmat[3]);
						VecAddf(cent, cent, ob__obmat[3]);
						
						Mat4CpyMat4(obmat, ob__obmat);
						
						VECCOPY(obmat[3], cent);
						
						/* rotation */
						triatoquat(v1, v2, v3, quat);
						QuatToMat3(quat, mat);
						
						/* scale */
						if(par->transflag & OB_DUPLIFACES_SCALE) {
							float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3);
							size= sqrt(size) * par->dupfacesca;
							Mat3MulFloat(mat[0], size);
						}
						
						Mat3CpyMat3(mat3, mat);
						Mat3MulMat3(mat, imat, mat3);
						
						Mat4CpyMat4(tmat, obmat);
						Mat4MulMat43(obmat, tmat, mat);
						
						dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated);
						if(G.rendering) {
							w= (mv4)? 0.25f: 1.0f/3.0f;

							if(orco) {
								VECADDFAC(dob->orco, dob->orco, orco[mv1], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv2], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv3], w);
								if(mv4)
									VECADDFAC(dob->orco, dob->orco, orco[mv4], w);
							}

							if(mtface) {
								dob->uv[0] += w*mtface[a].uv[0][0];
								dob->uv[1] += w*mtface[a].uv[0][1];
								dob->uv[0] += w*mtface[a].uv[1][0];
								dob->uv[1] += w*mtface[a].uv[1][1];
								dob->uv[0] += w*mtface[a].uv[2][0];
								dob->uv[1] += w*mtface[a].uv[2][1];

								if(mv4) {
									dob->uv[0] += w*mtface[a].uv[3][0];
									dob->uv[1] += w*mtface[a].uv[3][1];
								}
							}
						}
						
						if(ob->transflag & OB_DUPLI) {
							float tmpmat[4][4];
							Mat4CpyMat4(tmpmat, ob->obmat);
							Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated);
							Mat4CpyMat4(ob->obmat, tmpmat);
						}
					}
					
					break;
				}
				ob= ob->parent;
			}
		}
		if (sce)	base= base->next;	/* scene loop */
		else		go= go->next;		/* group loop */
	}
	
	if(par->mode & OB_MODE_EDIT) {
		MEM_freeN(mface);
		MEM_freeN(mvert);
	}

	if(orco)
		MEM_freeN(orco);
	
	dm->release(dm);
}
Beispiel #6
0
static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
{
	int displaymode = 0;
	int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */
	char targetFile[FILE_MAX];
	FluidsimSettings *fss = fluidmd->fss;
	DerivedMesh *dm = NULL;
	MFace *mface;
	int numfaces;
	int mat_nr, flag, i;

	if(!useRenderParams) {
		displaymode = fss->guiDisplayMode;
	} else {
		displaymode = fss->renderDisplayMode;
	}

	switch (displaymode) {
	case 1:
		/* just display original object */
		return NULL;
	case 2:
		/* use preview mesh */
		BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
		break;
	default: /* 3 */
		/* 3. use final mesh */
		BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
		break;
	}

	BLI_path_abs(targetFile, modifier_path_relbase(ob));
	BLI_path_frame(targetFile, curFrame, 0); // fixed #frame-no

	dm = fluidsim_read_obj(targetFile);

	if(!dm)
	{
		// switch, abort background rendering when fluidsim mesh is missing
		const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp

		if(G.background==1) {
			if(getenv(strEnvName2)) {
				int elevel = atoi(getenv(strEnvName2));
				if(elevel>0) {
					printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
					exit(1);
				}
			}
		}

		// display org. object upon failure which is in dm
		return NULL;
	}

	// assign material + flags to new dm
	// if there's no faces in original dm, keep materials and flags unchanged
	mface = orgdm->getFaceArray(orgdm);

	if(mface) {
		mat_nr = mface[0].mat_nr;
		flag = mface[0].flag;

		mface = dm->getFaceArray(dm);
		numfaces = dm->getNumFaces(dm);
		for(i=0; i<numfaces; i++)
			{
				mface[i].mat_nr = mat_nr;
				mface[i].flag = flag;
			}
	}

	// load vertex velocities, if they exist...
	// TODO? use generate flag as loading flag as well?
	// warning, needs original .bobj.gz mesh loading filename
	if(displaymode==3)
	{
		fluidsim_read_vel_cache(fluidmd, dm, targetFile);
	}
	else
	{
		if(fss->meshVelocities)
			MEM_freeN(fss->meshVelocities);

		fss->meshVelocities = NULL;
	}

	return dm;
}
Beispiel #7
0
static void createVertsTrisData(bContext *C, LinkNode* obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r)
{
	MVert *mvert;
	int nfaces= 0, *tri, i, curnverts, basenverts, curnfaces;
	MFace *mface;
	float co[3], wco[3];
	Object *ob;
	LinkNode *oblink, *dmlink;
	DerivedMesh *dm;
	Scene* scene= CTX_data_scene(C);
	LinkNode* dms= NULL;

	int nverts, ntris, *tris;
	float *verts;

	nverts= 0;
	ntris= 0;

	/* calculate number of verts and tris */
	for(oblink= obs; oblink; oblink= oblink->next) {
		ob= (Object*) oblink->link;
		dm= mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
		BLI_linklist_append(&dms, (void*)dm);

		nverts+= dm->getNumVerts(dm);
		nfaces= dm->getNumFaces(dm);
		ntris+= nfaces;

		/* resolve quad faces */
		mface= dm->getFaceArray(dm);
		for(i= 0; i<nfaces; i++) {
			MFace* mf= &mface[i];
			if(mf->v4)
				ntris+=1;
		}
	}

	/* create data */
	verts= MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts");
	tris= MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces");

	basenverts= 0;
	tri= tris;
	for(oblink= obs, dmlink= dms; oblink && dmlink;
			oblink= oblink->next, dmlink= dmlink->next) {
		ob= (Object*) oblink->link;
		dm= (DerivedMesh*) dmlink->link;

		curnverts= dm->getNumVerts(dm);
		mvert= dm->getVertArray(dm);

		/* copy verts */
		for(i= 0; i<curnverts; i++) {
			MVert *v= &mvert[i];

			copy_v3_v3(co, v->co);
			mul_v3_m4v3(wco, ob->obmat, co);

			verts[3*(basenverts+i)+0]= wco[0];
			verts[3*(basenverts+i)+1]= wco[2];
			verts[3*(basenverts+i)+2]= wco[1];
		}

		/* create tris */
		curnfaces= dm->getNumFaces(dm);
		mface= dm->getFaceArray(dm);

		for(i= 0; i<curnfaces; i++) {
			MFace* mf= &mface[i];

			tri[0]= basenverts + mf->v1;
			tri[1]= basenverts + mf->v3;
			tri[2]= basenverts + mf->v2;
			tri += 3;

			if(mf->v4) {
				tri[0]= basenverts + mf->v1;
				tri[1]= basenverts + mf->v4;
				tri[2]= basenverts + mf->v3;
				tri += 3;
			}
		}

		basenverts+= curnverts;
	}

	/* release derived mesh */
	for(dmlink= dms; dmlink; dmlink= dmlink->next) {
		dm= (DerivedMesh*) dmlink->link;
		dm->release(dm);
	}

	BLI_linklist_free(dms, NULL);

	*nverts_r= nverts;
	*verts_r= verts;
	*ntris_r= ntris;
	*tris_r= tris;
}