Exemple #1
0
void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexcos, int totvert, float cagemat[][4])
{
	MeshDeformBind mdb;
	MVert *mvert;
	int a;

	waitcursor(1);
	start_progress_bar();

	memset(&mdb, 0, sizeof(MeshDeformBind));

	/* get mesh and cage mesh */
	mdb.vertexcos= MEM_callocN(sizeof(float)*3*totvert, "MeshDeformCos");
	mdb.totvert= totvert;
	
	mdb.cagedm= mesh_create_derived_no_deform(scene, mmd->object, NULL, CD_MASK_BAREMESH);
	mdb.totcagevert= mdb.cagedm->getNumVerts(mdb.cagedm);
	mdb.cagecos= MEM_callocN(sizeof(*mdb.cagecos)*mdb.totcagevert, "MeshDeformBindCos");
	copy_m4_m4(mdb.cagemat, cagemat);

	mvert= mdb.cagedm->getVertArray(mdb.cagedm);
	for(a=0; a<mdb.totcagevert; a++)
		copy_v3_v3(mdb.cagecos[a], mvert[a].co);
	for(a=0; a<mdb.totvert; a++)
		mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a*3);

	/* solve */
#if 0
	if(mmd->mode == MOD_MDEF_VOLUME)
		harmonic_coordinates_bind(scene, mmd, &mdb);
	else
		heat_weighting_bind(scene, dm, mmd, &mdb);
#else
	harmonic_coordinates_bind(scene, mmd, &mdb);
#endif

	/* assign bind variables */
	mmd->bindcagecos= (float*)mdb.cagecos;
	mmd->totvert= mdb.totvert;
	mmd->totcagevert= mdb.totcagevert;
	copy_m4_m4(mmd->bindmat, mmd->object->obmat);

	/* transform bindcagecos to world space */
	for(a=0; a<mdb.totcagevert; a++)
		mul_m4_v3(mmd->object->obmat, mmd->bindcagecos+a*3);

	/* free */
	mdb.cagedm->release(mdb.cagedm);
	MEM_freeN(mdb.vertexcos);

	/* compact weights */
	modifier_mdef_compact_influences((ModifierData*)mmd);

	end_progress_bar();
	waitcursor(0);
}
Exemple #2
0
void image_preview_event(int event)
{
	int exec = 0;
	
	if (event == 0) {
		G.scene->r.scemode &= ~R_COMP_CROP;
		exec = 1;
	}
	else {
		if (image_preview_active(curarea, NULL, NULL)) {
			G.scene->r.scemode |= R_COMP_CROP;
			exec = 1;
		}
		else
			G.scene->r.scemode &= ~R_COMP_CROP;
	}
	
	if (exec && G.scene->nodetree) {
		Scene *scene = G.scene;
		/* should work when no node editor in screen..., so we execute right away */
		
		ntreeCompositTagGenerators(G.scene->nodetree);

		G.is_break = FALSE;
		G.scene->nodetree->timecursor = set_timecursor;
		G.scene->nodetree->test_break = blender_test_break;
		
		BIF_store_spare();
		
		ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings);   /* 1 is do_previews */
		
		G.scene->nodetree->timecursor = NULL;
		G.scene->nodetree->test_break = NULL;
		
		scrarea_do_windraw(curarea);
		waitcursor(0);
		
		WM_event_add_notifier(C, NC_IMAGE, ima_v);
	}
}
Exemple #3
0
void comap(void)
{
  int     k;
  int     maxkeys, icolort,
          maxreg, ix, iy, numtot, numcor, lastkey,
          doc_read, pkey;
  float   *plist = NULL, *ptr, *dbuf, xt, yt;
  double  davx, davx2, davy, davy2, bx, by, xmin, xmax, ymin, ymax, xr, yr,
          sigx, sigy, xrange, yrange;
  char    outstr[81];
     
  /* Set wait cursor */
  waitcursor(iwin, TRUE, 79);                                  
  
  /* 
  Recover all the lines from the doc file and store in the dbuf array.
  column 1 is the key, following columns are registers. correspondence
  analysis may have up to 24 registers. */

  doc_read = TRUE;
  pkey     = 0;
  maxkeys  = MYMAX(key1,key2) + 1;
  maxreg   = MYMAX(itxreg,ityreg) + 1;
  dbuf     = (float *) NULL;
  if (unsdal(docxnam, &doc_read, pkey, plist, maxreg, &dbuf, &lastkey,
                   maxkeys,maxreg) > 0)
      {
      /* Problem retrieving doc file, assume it does not exist */
      if (dbuf) free(dbuf);
      sprintf(outstr," Could not read document file: %s",docxnam);
      spout(outstr);

      /* unset wait cursor */
      waitcursor(iwin, FALSE, 0);                                  
      return;
      }
  
  if (lastkey < MYMIN(key1,key2))
      {
      if (dbuf) free(dbuf);
      sprintf(outstr," both keys needed %d & %d > lastkey = %d",
         key1,key2,lastkey);
      spout(outstr);

      /* unset wait cursor */
      waitcursor(iwin, FALSE, 0);                                  
      return;
      } 
      
  /* Determine maximum/minimum x and y coordinates, avg, etc; */
  xmin = ymin = FLT_MAX;
  xmax = ymax = -xmin;

  davx = davx2 = davy = davy2 = 0; 

  /* Run time allocate of memory space for nkey[], bufx, bufy */
  if ( (nkey = (int *) calloc((key1 * key2), sizeof(float)) )
             == (int *) NULL)                                       {
     spout(" *** Could not allocate memory");
     waitcursor(iwin, FALSE, 0);  return;                           }
  if ( (bufx = (float *) calloc((key1 * key2), sizeof(float)) )
             == (float *) NULL)                                     {
     spout(" *** Could not allocate memory");
     waitcursor(iwin, FALSE, 0);  return;                           }
  if ( (bufy = (float *) calloc((key1 * key2), sizeof(float)) )
             == (float *) NULL)                                     {
     spout(" ***Could not allocate memory");
     waitcursor(iwin, FALSE, 0);  return;                           }

  /* Remember current color in icontx */
  icolort = icolor;

  /* Set current color to image almost white */
  wicolor(icontx,colorgo+2);

  /* Clear the screen */
  //clearover(NULL,NULL,NULL);

  ptr   = dbuf + (key1-1) * maxreg;
  nline = 0;

  for (k = key1; k <= key2; k++)
      {
      /* Check that the key has some registers. */
      if ( (*ptr) > 0.0) 
          {
          nkey[nline] = k;          /*  image number      */
          bx = *(ptr + itxreg);     /*  dbuf[k][itxreg]   */
          by = *(ptr + ityreg);     /*  dbuf[k][ityreg]   */

          /* Record bx & by */
          bufx[nline] = bx;
          bufy[nline] = by;
          nline++;
    
          /* Record max and min for bx & by   */
          xmin = MYMIN(bx,xmin);
          xmax = MYMAX(bx,xmax);
          ymin = MYMIN(by,ymin);
          ymax = MYMAX(by,ymax);

          /* record average and standard deviation for bx & by */
          davx  += bx;
          davx2 += (double)(bx * bx);
          davy  += by;
          davy2 += (double)( by * by);
          }
      ptr += maxreg;
      }        /*   for (pkey = key1; pkey <= key2; pkey++)  */

  /* Calculate sigma and average */
  davx  /= (float) nline;
  davy  /= (float) nline;

  sigx   = sqrt((davx2 - (davx * davx / (float) nline)) / (double) (nline - 1));
  sigy   = sqrt((davy2 - (davy * davy / (float) nline)) / (double) (nline - 1));

  xt     = 2.0 * stndrt * sigx;
  yt     = 2.0 * stndrt * sigy;

  xr     = xmax - xmin;
  yr     = ymax - ymin;

  xrange = MYMIN(xt, xr);
  yrange = MYMIN(yt, yr);

  /* Set plot size */
  ixsize = iwidex - 2;
  iysize = ihighx - 2;
  ixmar  = iymar = 1;
  numtot = numcor = 0;

  /* Find scale factors */
  factxa = (float) (ixsize -1) / xrange;
  factxb = - (xmin * factxa) + ixmar + 0.5;

  factya = (float) (iysize-1) / yrange;
  factyb = - (ymin * factya) + iymar + 0.5;

  for (k = 0; k < nline; k++)
    {
      ix = (bufx[k] - xmin) * factxa + ixmar + 0.5;
      iy = (bufy[k] - ymin) * factya + iymar + 0.5;

      if (ix >= ixmar && ix <= ixsize && iy >= iymar && iy <= iysize)
          { /* Image is inside the plot extent; find the label number */

          if (sayno)
              {  /* write image number at this location on plot */
              sprintf(outstr,"%d",nkey[k]);
              //           itsize,just,  inten,ipen,  overprint
              witext(icontx,outstr,ix,iy, 0,0, -9,2,  FALSE);
              }
          else
              { 
              /* Draw a permanent circle at this position */
              xorc(iwin,    icontx, TRUE, ix, iy, itrad);
              xorc(imagsav, icontx, TRUE, ix, iy, itrad);
              }

          /* Increment total number of images within plot extent */
          numcor += 1;
          }
      else
        {
        /* Image is outside of plot extent */
        nkey[k] = - nkey[k];
        }

    numtot += 1;   /* Increment total number of images */
    }
  sprintf(outstr," Images: %d   Images within plot: %d",numtot,numcor);
  spout(outstr);
     
  /* Replace current color in icontx */
  wicolor(icontx,icolort);

  /* Initialize bin counter for this map */
  nowbin = 0;

  /* Set flag for each bin mask */
  gotbin = gotavim = gotav = FALSE;

  /* Cancel wait cursor */
  waitcursor(iwin, FALSE, 0);

  /* Start masking of correspondence map */
  corr_mask(0);
}
Exemple #4
0
void ED_object_enter_editmode(bContext *C, int flag)
{
	Scene *scene= CTX_data_scene(C);
	Base *base= NULL;
	Object *ob;
	ScrArea *sa= CTX_wm_area(C);
	View3D *v3d= NULL;
	int ok= 0;
	
	if (scene->id.lib) return;
	
	if (sa && sa->spacetype==SPACE_VIEW3D)
		v3d= sa->spacedata.first;
	
	if ((flag & EM_IGNORE_LAYER)==0) {
		base= CTX_data_active_base(C); /* active layer checked here for view3d */

		if (base==NULL) return;
		else if (v3d && (base->lay & v3d->lay)==0) return;
		else if (!v3d && (base->lay & scene->lay)==0) return;
	}
	else {
		base= scene->basact;
	}

	if (ELEM3(NULL, base, base->object, base->object->data)) return;

	ob = base->object;
	
	if (object_data_is_libdata(ob)) {
		error_libdata();
		return;
	}
	
	if (flag & EM_WAITCURSOR) waitcursor(1);

	ob->restore_mode = ob->mode;

	/* note, when switching scenes the object can have editmode data but
	 * not be scene->obedit: bug 22954, this avoids calling self eternally */
	if ((ob->restore_mode & OB_MODE_EDIT)==0)
		ED_object_toggle_modes(C, ob->mode);

	ob->mode= OB_MODE_EDIT;
	
	if (ob->type==OB_MESH) {
		BMEditMesh *em;
		ok= 1;
		scene->obedit = ob;  /* context sees this */

		EDBM_mesh_make(CTX_data_tool_settings(C), scene, ob);

		em = BMEdit_FromObject(ob);
		if (LIKELY(em)) {
			/* order doesn't matter */
			EDBM_mesh_normals_update(em);
			BMEdit_RecalcTessellation(em);
			
			BM_mesh_select_mode_flush(em->bm);
		}

		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
	}
	else if (ob->type==OB_ARMATURE) {
		bArmature *arm= base->object->data;
		if (!arm) return;
		/*
		 * The function object_data_is_libdata make a problem here, the
		 * check for ob->proxy return 0 and let blender enter to edit mode
		 * this causes a crash when you try leave the edit mode.
		 * The problem is that i can't remove the ob->proxy check from
		 * object_data_is_libdata that prevent the bugfix #6614, so
		 * i add this little hack here.
		 */
		if (arm->id.lib) {
			error_libdata();
			return;
		}
		ok=1;
		scene->obedit= ob;
		ED_armature_to_edit(ob);
		/* to ensure all goes in restposition and without striding */
		DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX: should this be OB_RECALC_DATA?

		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, scene);
	}
	else if (ob->type==OB_FONT) {
		scene->obedit= ob; // XXX for context
		ok= 1;
		make_editText(ob);

		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_TEXT, scene);
	}
	else if (ob->type==OB_MBALL) {
		scene->obedit= ob; // XXX for context
		ok= 1;
		make_editMball(ob);

		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MBALL, scene);
	}
	else if (ob->type==OB_LATTICE) {
		scene->obedit= ob; // XXX for context
		ok= 1;
		make_editLatt(ob);
		
		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_LATTICE, scene);
	}
	else if (ob->type==OB_SURF || ob->type==OB_CURVE) {
		ok= 1;
		scene->obedit= ob; // XXX for context
		make_editNurb(ob);
		
		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_CURVE, scene);
	}
	
	if (ok) {
		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	}
	else {
		scene->obedit= NULL; // XXX for context
		ob->mode &= ~OB_MODE_EDIT;
		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
	}
	
	if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
	if (flag & EM_WAITCURSOR) waitcursor(0);
}
Exemple #5
0
void ED_object_exit_editmode(bContext *C, int flag)
{
	/* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */

	Scene *scene= CTX_data_scene(C);
	Object *obedit= CTX_data_edit_object(C);
	int freedata = flag & EM_FREEDATA;
	
	if (obedit==NULL) return;
	
	if (flag & EM_WAITCURSOR) waitcursor(1);
	if (obedit->type==OB_MESH) {
		Mesh *me= obedit->data;
		
//		if (EM_texFaceCheck())
		
		if (me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) {
			error("Too many vertices");
			return;
		}
		
		EDBM_mesh_load(obedit);
		
		if (freedata) {
			EDBM_mesh_free(me->edit_btmesh);
			MEM_freeN(me->edit_btmesh);
			me->edit_btmesh= NULL;
		}
		if (obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
			mesh_octree_table(NULL, NULL, NULL, 'e');
			mesh_mirrtopo_table(NULL, 'e');
		}
	}
	else if (obedit->type==OB_ARMATURE) {	
		ED_armature_from_edit(obedit);
		if (freedata)
			ED_armature_edit_free(obedit);
	}
	else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
		load_editNurb(obedit);
		if (freedata) free_editNurb(obedit);
	}
	else if (obedit->type==OB_FONT && freedata) {
		load_editText(obedit);
		if (freedata) free_editText(obedit);
	}
	else if (obedit->type==OB_LATTICE) {
		load_editLatt(obedit);
		if (freedata) free_editLatt(obedit);
	}
	else if (obedit->type==OB_MBALL) {
		load_editMball(obedit);
		if (freedata) free_editMball(obedit);
	}

	/* freedata only 0 now on file saves and render */
	if (freedata) {
		ListBase pidlist;
		PTCacheID *pid;

		/* for example; displist make is different in editmode */
		scene->obedit= NULL; // XXX for context

		/* flag object caches as outdated */
		BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0);
		for (pid=pidlist.first; pid; pid=pid->next) {
			if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
				pid->cache->flag |= PTCACHE_OUTDATED;
		}
		BLI_freelistN(&pidlist);
		
		BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);

		/* also flush ob recalc, doesn't take much overhead, but used for particles */
		DAG_id_tag_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
	
		if (flag & EM_DO_UNDO)
			ED_undo_push(C, "Editmode");
	
		if (flag & EM_WAITCURSOR) waitcursor(0);
	
		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);

		obedit->mode &= ~OB_MODE_EDIT;
	}
}
Exemple #6
0
 void backmen(int leftsidet)

 { 
 static Widget   iw_rowcolh;
 Widget          iw_rowcolv;
 Widget          iw_dums, iw_pushc, iw_pusha;
 float         * fptrdum = NULL;

 if (iw_backmen == (Widget)0)
    {   /* Create background enhancing menu widget first */

    iw_backmen  = wid_dialog(iw_win, 0, "Contrast options", -1,-1);
    iw_rowcolv  = wid_rowcol(iw_backmen, 'v', -1,-1);

    /* Create label for scales */
    wid_labelg(iw_rowcolv, 0,
               "Lower and upper end of ramp:", -1,-1);

    /* Create a horizontal row-col widget for scales */
    iw_rowcolh = wid_rowcol(iw_rowcolv, 'h', -1,-1);

    /* Create scale widget for starting value ------------------ ngo */
    iw_ngob  = wid_scale(iw_rowcolh, 0, "", 
                         imagego,imageend,  ngo, 
                         180,50, -1,-1);

    /* Create scale widget for ending value -------------------- nend */
    iw_nendb = wid_scale(iw_rowcolh, 0, "", 
                         imagego,imageend,  nend, 
                         180,50, -1,-1);

    XtAddCallback(iw_ngob, XmNvalueChangedCallback, 
                           (XtCallbackProc)backmen_butm,"0");
    XtAddCallback(iw_nendb,XmNvalueChangedCallback, 
                           (XtCallbackProc)backmen_butm,"0");

    /* Create box for apply ----------------------------------- apply */
    iw_dums = wid_stdbut(iw_rowcolv, iw_backmen, 
                        &iw_dums, &iw_pushc, &iw_pusha,  "CA",
                        fin_cb,fin_cb ,backmen_buta, NULL);
    }
 else
    {   /* Enhance menu widget already exists, update it */

    /* Alter scale widget for starting value ------------------- ngo */
    iw_ngob = wid_scale(iw_rowcolh, iw_ngob, "", 
                       imagego,imageend,  ngo, 
                       180,50, -1,-1);

    /* Alter scale widget for ending value  -------------------- nend */
    iw_nendb = wid_scale(iw_rowcolh, iw_nendb, "", 
                       imagego,imageend,  nend, 
                       180,50, -1,-1);
    }

 /* Set wait cursor */
 waitcursor(iwin, TRUE, 79);

 if (leftsidet)
    {
    /* Free up ximage buffer, before creating a new one */
    if (imagel) 
       { XFree((void *)imagel); imagel = NULL; } 

    /* Show left image using original ramp */                 
    nsam2 = nsaml; nrow2 = nrowl;
    showimage(filedatal, TRUE,   &cptrduml, 
                         TRUE,   &imagel,
                         FALSE,  &fptrdum, FALSE,
                         (float) filedatal->fmin_spi, 
                         (float) filedatal->fmax_spi,
                         imagego, imageend);    

    /* Shift left image to shifted location & display */
    pickdisp(TRUE, FALSE);
    }
 else
    {
    /* Show right image using original ramp */                       
    nsam2 = nsamr; nrow2 = nrowr;

    /* Free up ximage buffer, before creating a new one */
    if (imager) 
       { XFree((void *)imager); imager = NULL; } 

    showimage(filedatar, TRUE,   &cptrdumr, 
                         TRUE,   &imager,
                         FALSE,  &fptrdum, FALSE,
                         (float) filedatar->fmin_spi, 
                         (float) filedatar->fmax_spi,   
                         imagego, imageend);    

    /* Shift right image to shifted location and display */      
    pickdisp(FALSE, TRUE);
    }

 leftside = leftsidet;

 /* Cancel waitcursor */
 waitcursor(iwin, FALSE, 79);

 XtManageChild(iw_backmen);

 }
Exemple #7
0
 void backmen_buta(Widget iw_temp, XtPointer data, 
                                   XtPointer calldata)

 {
 float      fmint, fmaxt;
 float      *fptrdum = NULL;

 /* Remove menu */
 XtUnmanageChild(iw_backmen);

 /* Set wait cursor */
 waitcursor(iwin, TRUE, 79);

 /* Set location for images */ 
 placed = TRUE;
 if (leftside)
    {
    ixuln  = ixull;  iyuln = iyull;
    nsam2 = nsaml; nrow2 = nrowl;

    /* Find new displayed levels of fmin_spi and fmax_spi for left image */
    fmint = (((float)(ngo - imagego) / (float)(imageend - imagego))) * 
            (filedatal->fmax_spi - filedatal->fmin_spi) + filedatal->fmin_spi;

    fmaxt = (((float)(nend - imagego) / (float)(imageend - imagego))) * 
            (filedatal->fmax_spi - filedatal->fmin_spi)+ filedatal->fmin_spi;
 
    /* Free up ximage buffer, before creating a new one */
    if (imagel) 
       { XFree((void *)imagel); imagel =  NULL;  } 

    /* Show left image using new ramp */
    showimage(filedatal, TRUE,  &cptrduml, 
                         TRUE,  &imagel,
                         FALSE, &fptrdum, FALSE,
                         fmint, fmaxt, imagego, imageend);

    /* Shift left image to shifted location and display */
    pickdisp(TRUE, FALSE);
    }
 else
    {
    /* Set location for right images */ 
    placed = TRUE;
    ixuln  = ixulr;  iyuln = iyulr;
    nsam2  = nsamr;  nrow2 = nrowr;

    /* Find new displayed levels of fmin_spi and fmax_spi for right image */
    fmint = (((float)(ngo - imagego) / (float)(imageend - imagego))) * 
            (filedatar->fmax_spi - filedatar->fmin_spi) + filedatar->fmin_spi;

    fmaxt = (((float)(nend - imagego) / (float)(imageend - imagego))) * 
            (filedatar->fmax_spi - filedatar->fmin_spi) + filedatar->fmin_spi;

    /* Free up ximage buffer, before creating a new one */
    if (imager) 
       {  XFree((void *)imager); imager = NULL;  } 
   
    /* Show right image using new ramp */
    showimage(filedatar, TRUE,  &cptrdumr, 
                         TRUE,  &imager, 
                         FALSE, &fptrdum, FALSE,
                         fmint, fmaxt, imagego, imageend);

    /* Shift right image to shifted location and display */      
    pickdisp(FALSE, TRUE);
    }

  //printf ("%d...%d   File Range: %7.2f ...%7.2f \n",imagego,imageend, 
  //          filedatar->fmin_spi,filedatar->fmax_spi);
  //printf ("%d...%d   Range: %7.2f ...%7.2f \n",ngo,nend, fmint,fmaxt);
 
 /* Apply normal uncontrasted ramp to whole image */
 ngo  = imagego;
 nend = imageend;

 XmScaleSetValue(iw_ngob,  ngo);
 XmScaleSetValue(iw_nendb, nend);

 /* Apply normal uncontrasted ramp to whole screen */
 backmen_butm(NULL,NULL,NULL);

 /* Cancel waitcursor */
 waitcursor(iwin, FALSE, 79);

 return; 
 }
Exemple #8
0
int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
{
	Scene *scene= CTX_data_scene(C);
	FILE *fileCfg;
	int i;
	Object *fsDomain = NULL;
	FluidsimSettings *domainSettings;
	Object *obit = NULL; /* object iterator */
	Base *base;
	int origFrame = scene->r.cfra;
	char debugStrBuffer[256];
	int dirExist = 0;
	int gridlevels = 0;
	int simAborted = 0; // was the simulation aborted by user?
	int  doExportOnly = 0;
	char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY";
	const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
	//char *channelNames[3] = { "translation","rotation","scale" };

	char *suffixConfig = "fluidsim.cfg";
	char *suffixSurface = "fluidsurface";
	char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
	char targetDir[FILE_MAXDIR+FILE_MAXFILE];  // store & modify output settings
	char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
	int  outStringsChanged = 0;             // modified? copy back before baking
	int  haveSomeFluid = 0;                 // check if any fluid objects are set

	// config vars, inited before either export or run...
	double calcViscosity = 0.0;
	int noFrames;
	double aniFrameTime;
	float aniFrlen;
	int   channelObjCount;
	float *bbStart = NULL;
	float *bbSize = NULL;
	float domainMat[4][4];
	float invDomMat[4][4];
	// channel data
	int   allchannelSize; // fixed by no. of frames
	int   startFrame = 1;  // dont use scene->r.sfra here, always start with frame 1
	// easy frame -> sim time calc
	float *timeAtFrame=NULL, *timeAtIndex=NULL;
	// domain
	float *channelDomainTime = NULL;
	float *channelDomainViscosity = NULL; 
	float *channelDomainGravity = NULL;
	// objects (currently max. 256 objs)
	float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
	float *channelObjInivel[256];    // initial velocities
	float *channelObjActive[256];    // obj active channel
	
	/* fluid control channels */
	float *channelAttractforceStrength[256];
	float *channelAttractforceRadius[256];
	float *channelVelocityforceStrength[256];
	float *channelVelocityforceRadius[256];
	FluidsimModifierData *fluidmd = NULL;
	Mesh *mesh = NULL;
	
	if(getenv(strEnvName)) {
		int dlevel = atoi(getenv(strEnvName));
		elbeemSetDebugLevel(dlevel);
		snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); 
		elbeemDebugOut(debugStrBuffer);
	}
	if(getenv(exportEnvStr)) {
		doExportOnly = atoi(getenv(exportEnvStr));
		snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); 
		elbeemDebugOut(debugStrBuffer);
	}

	// make sure it corresponds to startFrame setting
	// old: noFrames = scene->r.efra - scene->r.sfra +1;
	noFrames = scene->r.efra - 0;
	if(noFrames<=0) {
		BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings.");
		return 0;
	}

	/* no object pointer, find in selected ones.. */
	if(!ob) {
		for(base=scene->base.first; base; base= base->next) {
			if ((base)->flag & SELECT) 
			{
				FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
				
				if(fluidmdtmp && (base->object->type==OB_MESH)) 
				{
					if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
					{
						ob = base->object;
						break;
					}
				}
			}
		}
		// no domains found?
		if(!ob) return 0;
	}
	
	channelObjCount = 0;
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp && 
			(obit->type==OB_MESH) &&
			(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
			(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) 
		{
			channelObjCount++;
		}
	}
	
	if (channelObjCount>=255) {
		BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects.");
		return 0;
	}

	/* check if there's another domain... */
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp &&(obit->type==OB_MESH)) 
		{
			if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
			{
				if(obit != ob) 
				{
					BKE_report(reports, RPT_ERROR, "There should be only one domain object.");
					return 0;
				}
			}
		}
	}
	
	// check if theres any fluid
	// abort baking if not...
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp && 
			(obit->type==OB_MESH) && 
			((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
			(fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
		{
			haveSomeFluid = 1;
			break;
		}
	}
	if(!haveSomeFluid) {
		BKE_report(reports, RPT_ERROR, "No fluid objects in scene.");
		return 0;
	}
	
	/* these both have to be valid, otherwise we wouldnt be here */
	/* dont use ob here after...*/
	fsDomain = ob;
	fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
	domainSettings = fluidmd->fss;
	ob = NULL;
	mesh = fsDomain->data;
	
	// calculate bounding box
	fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
	
	// reset last valid frame
	domainSettings->lastgoodframe = -1;
	
	/* rough check of settings... */
	if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
		snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz ,  domainSettings->resolutionxyz); 
		elbeemDebugOut(debugStrBuffer);
		domainSettings->previewresxyz = domainSettings->resolutionxyz;
	}
	// set adaptive coarsening according to resolutionxyz
	// this should do as an approximation, with in/outflow
	// doing this more accurate would be overkill
	// perhaps add manual setting?
	if(domainSettings->maxRefine <0) {
		if(domainSettings->resolutionxyz>128) {
			gridlevels = 2;
		} else
		if(domainSettings->resolutionxyz>64) {
			gridlevels = 1;
		} else {
			gridlevels = 0;
		}
	} else {
		gridlevels = domainSettings->maxRefine;
	}
	snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); 
	elbeemDebugOut(debugStrBuffer);

	// prepare names...
	strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
	strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
	BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no 

	strcpy(targetFile, targetDir);
	strcat(targetFile, suffixConfig);
	if(!doExportOnly) { strcat(targetFile,".tmp"); }  // dont overwrite/delete original file
	// make sure all directories exist
	// as the bobjs use the same dir, this only needs to be checked
	// for the cfg output
	BLI_make_existing_file(targetFile);

	// check selected directory
	// simply try to open cfg file for writing to test validity of settings
	fileCfg = fopen(targetFile, "w");
	if(fileCfg) { 
		dirExist = 1; fclose(fileCfg); 
		// remove cfg dummy from  directory test
		if(!doExportOnly) { BLI_delete(targetFile, 0,0); }
	}

	if((strlen(targetDir)<1) || (!dirExist)) {
		char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE];
		// invalid dir, reset to current/previous
		strcpy(blendDir, G.sce);
		BLI_splitdirstring(blendDir, blendFile);
		if(strlen(blendFile)>6){
			int len = strlen(blendFile);
			if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&&
					(blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){
				blendFile[len-6] = '\0';
			}
		}
		// todo... strip .blend ?
		snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);

		snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
		elbeemDebugOut(debugStrBuffer);
		outStringsChanged=1;
	}

	// check if modified output dir is ok
	if(outStringsChanged) {
		char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
		int  selection=0;
		strcpy(dispmsg,"Output settings set to: '");
		strcat(dispmsg, newSurfdataPath);
		strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");

		// ask user if thats what he/she wants...
		selection = pupmenu(dispmsg);
		if(selection<1) return 0; // 0 from menu, or -1 aborted
		strcpy(targetDir, newSurfdataPath);
		strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
		BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no 
	}
	
	// --------------------------------------------------------------------------------------------
	// dump data for start frame 
	// CHECK more reasonable to number frames according to blender?
	// dump data for frame 0
	scene->r.cfra = startFrame;
	ED_update_for_newframe(C, 1);
	
	// init common export vars for both file export and run
	for(i=0; i<256; i++) {
		channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
		channelObjInivel[i] = NULL;
		channelObjActive[i] = NULL;
		channelAttractforceStrength[i] = NULL;
		channelAttractforceRadius[i] = NULL;
		channelVelocityforceStrength[i] = NULL;
		channelVelocityforceRadius[i] = NULL;
	}
	allchannelSize = scene->r.efra; // always use till last frame
	aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
	// blender specific - scale according to map old/new settings in anim panel:
	aniFrlen = scene->r.framelen;
	if(domainSettings->viscosityMode==1) {
		/* manual mode, visc=value/(10^-vexp) */
		calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue;
	} else {
		calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
	}

	bbStart = domainSettings->bbStart;
	bbSize = domainSettings->bbSize;

	// always init
	{ int timeIcu[1] = { FLUIDSIM_TIME };
		float timeDef[1] = { 1. };
		int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z };
		float gravDef[3];
		int viscIcu[1] = { FLUIDSIM_VISC };
		float viscDef[1] = { 1. };

		gravDef[0] = domainSettings->gravx;
		gravDef[1] = domainSettings->gravy;
		gravDef[2] = domainSettings->gravz;

		// time channel is a bit special, init by hand...
		timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
		for(i=0; i<=scene->r.efra; i++) {
			timeAtIndex[i] = (float)(i-startFrame);
		}
		fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
		// time channel is a multiplicator for aniFrameTime
		if(channelDomainTime) {
			for(i=0; i<allchannelSize; i++) { 
				channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0]; 
				if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.;
			}
		}
		timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe");
		timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1
		if(channelDomainTime) {
			for(i=2; i<=allchannelSize; i++) {
				timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
			}
		} else {
			for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
		}

		fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
		if(channelDomainViscosity) {
			for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; }
		}
		fluidsimInitChannel(scene, &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC );
	} // domain channel init
	
	// init obj movement channels
	channelObjCount=0;
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		
		if( fluidmdtmp && 
			(obit->type==OB_MESH) &&
			(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
			(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {

			//  cant use fluidsimInitChannel for obj channels right now, due
			//  to the special DXXX channels, and the rotation specialities
			IpoCurve *icuex[3][3];
			//IpoCurve *par_icuex[3][3];
#if 0
			int icuIds[3][3] = { 
				{OB_LOC_X,  OB_LOC_Y,  OB_LOC_Z},
				{OB_ROT_X,  OB_ROT_Y,  OB_ROT_Z},
				{OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} 
			};
			int icudIds[3][3] = { 
				{OB_DLOC_X,  OB_DLOC_Y,  OB_DLOC_Z},
				{OB_DROT_X,  OB_DROT_Y,  OB_DROT_Z},
				{OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} 
			};
#endif
			// relative ipos
			IpoCurve *icudex[3][3];
			//IpoCurve *par_icudex[3][3];
			int j,k;
			float vals[3] = {0.0,0.0,0.0}; 
			int o = channelObjCount;
			int   inivelIcu[3] =  { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z };
			float inivelDefs[3];
			int   activeIcu[1] =  { FLUIDSIM_ACTIVE };
			float activeDefs[1] = { 1 }; // default to on

			inivelDefs[0] = fluidmdtmp->fss->iniVelx;
			inivelDefs[1] = fluidmdtmp->fss->iniVely;
			inivelDefs[2] = fluidmdtmp->fss->iniVelz;

			// check & init loc,rot,size
			for(j=0; j<3; j++) {
				for(k=0; k<3; k++) {
					// XXX prevent invalid memory access until this works
					icuex[j][k]= NULL;
					icudex[j][k]= NULL;

					// XXX icuex[j][k]  = find_ipocurve(obit->ipo, icuIds[j][k] );
					// XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] );
					// XXX lines below were already disabled!
					//if(obit->parent) {
						//par_icuex[j][k]  = find_ipocurve(obit->parent->ipo, icuIds[j][k] );
						//par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] );
					//}
				}
			}

			for(j=0; j<3; j++) {
				channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel");
				for(i=1; i<=allchannelSize; i++) {

					for(k=0; k<3; k++) {
						if(icuex[j][k]) { 
							// IPO exists, use it ...
							// XXX calc_icu(icuex[j][k], aniFrlen*((float)i) );
							vals[k] = icuex[j][k]->curval; 
							if(obit->parent) {
								// add parent transform, multiply scaling, add trafo&rot
								//calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
								//if(j==2) { vals[k] *= par_icuex[j][k]->curval; }
								//else { vals[k] += par_icuex[j][k]->curval; }
							}
						} else {
							// use defaults from static values
							float setval=0.0;
							if(j==0) { 
								setval = obit->loc[k];
								if(obit->parent){ setval += obit->parent->loc[k]; }
							} else if(j==1) { 
								setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI );
								if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); }
							} else { 
								setval = obit->size[k]; 
								if(obit->parent){ setval *= obit->parent->size[k]; }
							}
							vals[k] = setval;
						}
						if(icudex[j][k]) { 
							// XXX calc_icu(icudex[j][k], aniFrlen*((float)i) );
							//vals[k] += icudex[j][k]->curval; 
							// add transform, multiply scaling, add trafo&rot
							if(j==2) { vals[k] *= icudex[j][k]->curval; }
							else { vals[k] += icudex[j][k]->curval; }
							if(obit->parent) {
								// add parent transform, multiply scaling, add trafo&rot
								//calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
								//if(j==2) { vals[k] *= par_icudex[j][k]->curval; }
								//else { vals[k] += par_icudex[j][k]->curval; }
							}
						} 
					} // k

					for(k=0; k<3; k++) {
						float set = vals[k];
						if(j==1) { // rot is downscaled by 10 for ipo !?
							set = 360.0 - (10.0*set);
						}
						channelObjMove[o][j][(i-1)*4 + k] = set;
					} // k
					channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
				}
			}
			
			{
				int   attrFSIcu[1] =  { FLUIDSIM_ATTR_FORCE_STR };
				int   attrFRIcu[1] =  { FLUIDSIM_ATTR_FORCE_RADIUS };
				int   velFSIcu[1] =  { FLUIDSIM_VEL_FORCE_STR };
				int   velFRIcu[1] =  { FLUIDSIM_VEL_FORCE_RADIUS };

				float attrFSDefs[1];
				float attrFRDefs[1];
				float velFSDefs[1];
				float velFRDefs[1];
				
				attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
				attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
				velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
				velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
				
				fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
			}
			
			fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
			fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
		

			channelObjCount++;

		}
	}

	// init trafo matrix
	Mat4CpyMat4(domainMat, fsDomain->obmat);
	if(!Mat4Invert(invDomMat, domainMat)) {
		snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); 
		elbeemDebugOut(debugStrBuffer);
		BKE_report(reports, RPT_ERROR, "Invalid object matrix."); 
		// FIXME add fatal msg
		FS_FREE_CHANNELS;
		return 0;
	}

	// --------------------------------------------------------------------------------------------
	// start writing / exporting
	strcpy(targetFile, targetDir);
	strcat(targetFile, suffixConfig);
	if(!doExportOnly) { strcat(targetFile,".tmp"); }  // dont overwrite/delete original file
	// make sure these directories exist as well
	if(outStringsChanged) {
		BLI_make_existing_file(targetFile);
	}

	if(!doExportOnly) {
		ListBase threads;

		// perform simulation with El'Beem api and threads
		elbeemSimulationSettings fsset;
		elbeemResetSettings(&fsset);
		fsset.version = 1;

		// setup global settings
		for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
		for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
		
		// simulate with 50^3
		fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
		fsset.previewresxyz = (int)domainSettings->previewresxyz;
		// 10cm water domain
		fsset.realsize = domainSettings->realsize;
		fsset.viscosity = calcViscosity;
		// earth gravity
		fsset.gravity[0] = domainSettings->gravx;
		fsset.gravity[1] = domainSettings->gravy;
		fsset.gravity[2] = domainSettings->gravz;
		// simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
		fsset.animStart = domainSettings->animStart;
		fsset.aniFrameTime = aniFrameTime;
		fsset.noOfFrames = noFrames; // is otherwise subtracted in parser
		strcpy(targetFile, targetDir);
		strcat(targetFile, suffixSurface);
		// defaults for compressibility and adaptive grids
		fsset.gstar = domainSettings->gstar;
		fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels
		fsset.generateParticles = domainSettings->generateParticles; 
		fsset.numTracerParticles = domainSettings->generateTracers; 
		fsset.surfaceSmoothing = domainSettings->surfaceSmoothing; 
		fsset.surfaceSubdivs = domainSettings->surfaceSubdivs; 
		fsset.farFieldSize = domainSettings->farFieldSize; 
		strcpy( fsset.outputPath, targetFile);

		// domain channels
		fsset.channelSizeFrameTime = 
		fsset.channelSizeViscosity = 
		fsset.channelSizeGravity =  allchannelSize;
		fsset.channelFrameTime = channelDomainTime;
		fsset.channelViscosity = channelDomainViscosity;
		fsset.channelGravity = channelDomainGravity;

		fsset.runsimCallback = &runSimulationCallback;
		fsset.runsimUserData = &fsset;

		if(     (domainSettings->typeFlags&OB_FSBND_NOSLIP))   fsset.domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
		else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
		else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
		fsset.domainobsPartslip = domainSettings->partSlipValue;
		fsset.generateVertexVectors = (domainSettings->domainNovecgen==0);

		// init blender trafo matrix
 		// fprintf(stderr,"elbeemInit - mpTrafo:\n");
		{ int j; 
		for(i=0; i<4; i++) {
			for(j=0; j<4; j++) {
				fsset.surfaceTrafo[i*4+j] = invDomMat[j][i];
 				// fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) );
			}
		} }

	  // init solver with settings
		elbeemInit();
		elbeemAddDomain(&fsset);
		
		// init objects
		channelObjCount = 0;
		for(base=scene->base.first; base; base= base->next) {
			FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
			obit = base->object;
			//{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
			if( fluidmdtmp &&  // if has to match 3 places! // CHECKMATCH
				(obit->type==OB_MESH) &&
				(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
				(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) 
			{
				float *verts=NULL;
				int *tris=NULL;
				int numVerts=0, numTris=0;
				int o = channelObjCount;
				int	deform = (fluidmdtmp->fss->domainNovecgen); // misused value
				// todo - use blenderInitElbeemMesh
				int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp);
				
				elbeemMesh fsmesh;
				elbeemResetMesh( &fsmesh );
				fsmesh.type = fluidmdtmp->fss->type;
				// get name of object for debugging solver
				fsmesh.name = obit->id.name; 

				initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
				fsmesh.numVertices   = numVerts;
				fsmesh.numTriangles  = numTris;
				fsmesh.vertices      = verts;
				fsmesh.triangles     = tris;

				fsmesh.channelSizeTranslation  = 
				fsmesh.channelSizeRotation     = 
				fsmesh.channelSizeScale        = 
				fsmesh.channelSizeInitialVel   = 
				fsmesh.channelSizeActive       = allchannelSize;

				fsmesh.channelTranslation      = channelObjMove[o][0];
				fsmesh.channelRotation         = channelObjMove[o][1];
				fsmesh.channelScale            = channelObjMove[o][2];
				fsmesh.channelActive           = channelObjActive[o];
				if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
				(fsmesh.type == OB_FLUIDSIM_INFLOW)) {
					fsmesh.channelInitialVel       = channelObjInivel[o];
					fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
				} 

				if(     (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP))   fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
				else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
				else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
				fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
				fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
				fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
				
				if(fsmesh.type == OB_FLUIDSIM_CONTROL)
				{
					// control fluids will get exported as whole
					deform = 1;
					
					fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
					fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
					fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
					fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE);
					
					fsmesh.channelSizeAttractforceRadius = 
					fsmesh.channelSizeVelocityforceStrength = 
					fsmesh.channelSizeVelocityforceRadius = 
					fsmesh.channelSizeAttractforceStrength = allchannelSize;
					
					fsmesh.channelAttractforceStrength = channelAttractforceStrength[o];
					fsmesh.channelAttractforceRadius = channelAttractforceRadius[o];
					fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o];
					fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o];
				}
				else 
				{
					// set channels to 0
					fsmesh.channelAttractforceStrength =
					fsmesh.channelAttractforceRadius = 
					fsmesh.channelVelocityforceStrength = 
					fsmesh.channelVelocityforceRadius = NULL; 
				}

				// animated meshes
				if(deform) {
					fsmesh.channelSizeVertices = allchannelSize;
					fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex);
					scene->r.cfra = startFrame;
					ED_update_for_newframe(C, 1);
					// remove channels
					fsmesh.channelTranslation      = 
					fsmesh.channelRotation         = 
					fsmesh.channelScale            = NULL; 
				} 

				elbeemAddMesh(&fsmesh);

				if(verts) MEM_freeN(verts);
				if(tris) MEM_freeN(tris);
				if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices);
				channelObjCount++;
			} // valid mesh
		} // objects
		//domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again
		
		// set to neutral, -1 means user abort, -2 means init error
		globalBakeState = 0;
		globalBakeFrame = 0;
		BLI_init_threads(&threads, fluidsimSimulateThread, 1);
		BLI_insert_thread(&threads, targetFile);
		
		{
			int done = 0;
			float noFramesf = (float)noFrames;
			float percentdone = 0.0;
			int lastRedraw = -1;
			
			g_break= 0;
			G.afbreek= 0;	/* blender_test_break uses this global */
			
			start_progress_bar();

			while(done==0) {
				char busy_mess[80];
				
				waitcursor(1);
				
				// lukep we add progress bar as an interim mesure
				percentdone = globalBakeFrame / noFramesf;
				sprintf(busy_mess, "baking fluids %d / %d       |||", globalBakeFrame, (int) noFramesf);
				progress_bar(percentdone, busy_mess );
				
				// longer delay to prevent frequent redrawing
				PIL_sleep_ms(2000);
				
				BLI_lock_thread(LOCK_CUSTOM1);
				if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
				BLI_unlock_thread(LOCK_CUSTOM1);

				if (!G.background) {
					g_break= blender_test_break();
					
					if(g_break)
					{
						// abort...
						BLI_lock_thread(LOCK_CUSTOM1);
						
						if(domainSettings)
							domainSettings->lastgoodframe = startFrame+globalBakeFrame;
						
						done = -1;
						globalBakeFrame = 0;
						globalBakeState = -1;
						simAborted = 1;
						BLI_unlock_thread(LOCK_CUSTOM1);
						break;
					}
				} 

				// redraw the 3D for showing progress once in a while...
				if(lastRedraw!=globalBakeFrame) {
#if 0					
					ScrArea *sa;
					scene->r.cfra = startFrame+globalBakeFrame;
					lastRedraw = globalBakeFrame;
					ED_update_for_newframe(C, 1);
					sa= G.curscreen->areabase.first;
					while(sa) {
						if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); }
						sa= sa->next;	
					} 
					screen_swapbuffers();
#endif
				} // redraw
			}
			end_progress_bar();
		}
		BLI_end_threads(&threads);
	} // El'Beem API init, thread creation 
	// --------------------------------------------------------------------------------------------
	else
	{ // write config file to be run with command line simulator
		BKE_report(reports, RPT_WARNING, "Config file export not supported.");
	} // config file export done!

	// --------------------------------------------------------------------------------------------
	FS_FREE_CHANNELS;

	// go back to "current" blender time
	waitcursor(0);
	
	if(globalBakeState >= 0)
	{
		if(domainSettings)
			domainSettings->lastgoodframe = startFrame+globalBakeFrame;
	}
	
	scene->r.cfra = origFrame;
	ED_update_for_newframe(C, 1);

	if(!simAborted) {
		char elbeemerr[256];

		// check if some error occurred
		if(globalBakeState==-2) {
			elbeemGetErrorString(elbeemerr);
			BKE_reportf(reports, RPT_ERROR, "Failed to initialize [Msg: %s]", elbeemerr);
			return 0;
		} // init error
	}
	
	// elbeemFree();
	return 1;
}