Index: intern/smoke/extern/smoke_API.h
===================================================================
--- intern/smoke/extern/smoke_API.h	(revision 30053)
+++ intern/smoke/extern/smoke_API.h	(working copy)
@@ -38,10 +38,10 @@
 void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles);
 
 // low res
-struct FLUID_3D *smoke_init(int *res, float *p0, float dt);
+struct FLUID_3D *smoke_init(int *res, float *p0);
 void smoke_free(struct FLUID_3D *fluid);
 
-void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta);
+void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
 void smoke_step(struct FLUID_3D *fluid, size_t framenr);
 
 float *smoke_get_density(struct FLUID_3D *fluid);
Index: intern/smoke/intern/FLUID_3D.cpp
===================================================================
--- intern/smoke/intern/FLUID_3D.cpp	(revision 30053)
+++ intern/smoke/intern/FLUID_3D.cpp	(working copy)
@@ -35,23 +35,17 @@
 #include <omp.h>
 #endif // PARALLEL 
 
-// boundary conditions of the fluid domain
-#define DOMAIN_BC_FRONT  0 // z
-#define DOMAIN_BC_TOP    1 // y
-#define DOMAIN_BC_LEFT   1 // x
-#define DOMAIN_BC_BACK   DOMAIN_BC_FRONT
-#define DOMAIN_BC_BOTTOM DOMAIN_BC_TOP
-#define DOMAIN_BC_RIGHT  DOMAIN_BC_LEFT
+#define DT_DEFAULT 0.1f;
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
-	_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f), _dt(dt)
+FLUID_3D::FLUID_3D(int *res, float *p0) :
+	_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
 {
 	// set simulation consts
-	// _dt = dt; // 0.10
+	_dt = DT_DEFAULT;	// just in case. set in step from a RNA factor
 	
 	// start point of array
 	_p0[0] = p0[0];
@@ -61,7 +55,6 @@
 	_iterations = 100;
 	_tempAmb = 0; 
 	_heatDiffusion = 1e-3;
-	_vorticityEps = 2.0;
 	_totalTime = 0.0f;
 	_totalSteps = 0;
 	_res = Vec3Int(_xRes,_yRes,_zRes);
@@ -77,9 +70,9 @@
 	
 	// scale the constants according to the refinement of the grid
 	_dx = 1.0f / (float)_maxRes;
-	float scaling = 64.0f / _maxRes;
-	scaling = (scaling < 1.0f) ? 1.0f : scaling;
-	_vorticityEps /= scaling;
+	_constant_scaling = 64.0f / _maxRes;
+	_constant_scaling = (_constant_scaling < 1.0f) ? 1.0f : _constant_scaling;
+	_vorticityEps = 2.0f / _constant_scaling; // Just in case set a default value
 
 	// allocate arrays
 	_totalCells   = _xRes * _yRes * _zRes;
@@ -126,30 +119,42 @@
 		_obstacles[x]    = false;
 	}
 
+	// boundary conditions of the fluid domain
+	// set default values -> vertically non-colliding
+	DOMAIN_BC_FRONT = true;
+	DOMAIN_BC_TOP = false;
+	DOMAIN_BC_LEFT = true;
+	DOMAIN_BC_BACK = DOMAIN_BC_FRONT;
+	DOMAIN_BC_BOTTOM = DOMAIN_BC_TOP;
+	DOMAIN_BC_RIGHT	= DOMAIN_BC_LEFT;
+
+	colloPrev = 1;	// default value
+
+
 	// set side obstacles
 	int index;
 	for (int y = 0; y < _yRes; y++)
 	for (int x = 0; x < _xRes; x++)
 	{
-		// front slab
+		// bottom slab
 		index = x + y * _xRes;
-		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
 
-		// back slab
+		// top slab
 		index += _totalCells - _slabSize;
-		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
 	}
 
 	for (int z = 0; z < _zRes; z++)
 	for (int x = 0; x < _xRes; x++)
 	{
-		// bottom slab
+		// front slab
 		index = x + z * _slabSize;
-		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
 
-		// top slab
+		// back slab
 		index += _slabSize - _xRes;
-		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
 	}
 
 	for (int z = 0; z < _zRes; z++)
@@ -163,6 +168,7 @@
 		index += _xRes - 1;
 		if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
 	}
+
 }
 
 FLUID_3D::~FLUID_3D()
@@ -193,10 +199,13 @@
 }
 
 // init direct access functions from blender
-void FLUID_3D::initBlenderRNA(float *alpha, float *beta)
+void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
 {
 	_alpha = alpha;
 	_beta = beta;
+	_dt_factor = dt_factor;
+	_vorticityRNA = vorticity;
+	_border_colli = border_colli;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -204,6 +213,18 @@
 //////////////////////////////////////////////////////////////////////
 void FLUID_3D::step()
 {
+	// If border rules have been changed
+	if (colloPrev != *_border_colli) {
+		setBorderCollisions();
+	}
+
+
+	// set delta time by dt_factor
+	_dt = (*_dt_factor) * DT_DEFAULT;
+	// set vorticity from RNA value
+	_vorticityEps = (*_vorticityRNA)/_constant_scaling;
+
+
 #if PARALLEL==1
 	int threadval = 1;
 	threadval = omp_get_max_threads();
@@ -246,6 +267,13 @@
 	#pragma omp single
 	{
 #endif
+	/*
+	* addForce() changed Temp values to preserve thread safety
+	* (previous functions in per thread loop still needed
+	*  original velocity data)
+	*
+	* So swap temp values to velocity
+	*/
 	SWAP_POINTERS(_xVelocity, _xVelocityTemp);
 	SWAP_POINTERS(_yVelocity, _yVelocityTemp);
 	SWAP_POINTERS(_zVelocity, _zVelocityTemp);
@@ -276,6 +304,10 @@
 	#pragma omp single
 	{
 #endif
+	/*
+	* For thread safety use "Old" to read
+	* "current" values but still allow changing values.
+	*/
 	SWAP_POINTERS(_xVelocity, _xVelocityOld);
 	SWAP_POINTERS(_yVelocity, _yVelocityOld);
 	SWAP_POINTERS(_zVelocity, _zVelocityOld);
@@ -334,6 +366,10 @@
 	}
 #endif
 
+	/*
+	* swap final velocity back to Velocity array
+	* from temp xForce storage
+	*/
 	SWAP_POINTERS(_xVelocity, _xForce);
 	SWAP_POINTERS(_yVelocity, _yForce);
 	SWAP_POINTERS(_zVelocity, _zForce);
@@ -351,6 +387,83 @@
 
 }
 
+
+// Set border collision model from RNA setting
+
+void FLUID_3D::setBorderCollisions() {
+
+
+	colloPrev = *_border_colli;		// saving the current value
+
+	// boundary conditions of the fluid domain
+
+	if (colloPrev == 0) {		// No collisions
+		DOMAIN_BC_FRONT = false;
+		DOMAIN_BC_TOP = false;
+		DOMAIN_BC_LEFT = false;
+	}
+	else if (colloPrev == 2) {	// Collide with all sides
+		DOMAIN_BC_FRONT = true;
+		DOMAIN_BC_TOP = true;
+		DOMAIN_BC_LEFT = true;
+	}
+	else	{	// Default values: Collide with "walls", but not top and bottom
+		DOMAIN_BC_FRONT = true;
+		DOMAIN_BC_TOP = false;
+		DOMAIN_BC_LEFT = true;
+	}
+
+	DOMAIN_BC_BACK = DOMAIN_BC_FRONT;
+	DOMAIN_BC_BOTTOM = DOMAIN_BC_TOP;
+	DOMAIN_BC_RIGHT	= DOMAIN_BC_LEFT;
+
+
+
+	// set side obstacles
+	int index;
+	for (int y = 0; y < _yRes; y++)
+	for (int x = 0; x < _xRes; x++)
+	{
+		// front slab
+		index = x + y * _xRes;
+		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// back slab
+		index += _totalCells - _slabSize;
+		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+
+	for (int z = 0; z < _zRes; z++)
+	for (int x = 0; x < _xRes; x++)
+	{
+		// bottom slab
+		index = x + z * _slabSize;
+		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// top slab
+		index += _slabSize - _xRes;
+		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+
+	for (int z = 0; z < _zRes; z++)
+	for (int y = 0; y < _yRes; y++)
+	{
+		// left slab
+		index = y * _xRes + z * _slabSize;
+		if(DOMAIN_BC_LEFT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// right slab
+		index += _xRes - 1;
+		if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+}
+
 //////////////////////////////////////////////////////////////////////
 // helper function to dampen co-located grid artifacts of given arrays in intervals
 // (only needed for velocity, strength (w) depends on testcase...
@@ -428,6 +541,10 @@
 			for (y = 1; y < _res[1]-1; y++)
 				for (x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
 					index = x + y*_res[0] + posslab;
+					/*
+					* Uses xForce as temporary storage to allow other threads to read
+					* old values from xVelocityTemp
+					*/
 					_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
 							_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
 							_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
@@ -450,6 +567,11 @@
 			for (y = 1; y < _res[1]-1; y++)
 				for (x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
 					index = x + y*_res[0] + posslab;
+
+					/*
+					* Uses xForce as temporary storage to allow other threads to read
+					* old values from xVelocityTemp
+					*/
 					_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
 							_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
 							_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
@@ -664,10 +786,10 @@
 	if(DOMAIN_BC_LEFT == 0)  setNeumannX(_xVelocity, _res, 0, _zRes);
 	else setZeroX(_xVelocity, _res, 0, _zRes); 
 
-	if(DOMAIN_BC_TOP == 0)   setNeumannY(_yVelocity, _res, 0, _zRes);
+	if(DOMAIN_BC_FRONT == 0)   setNeumannY(_yVelocity, _res, 0, _zRes);
 	else setZeroY(_yVelocity, _res, 0, _zRes); 
 
-	if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
+	if(DOMAIN_BC_TOP == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
 	else setZeroZ(_zVelocity, _res, 0, _zRes);
 
 	// calculate divergence
@@ -1063,10 +1185,10 @@
 	if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
 	else setZeroX(_xVelocityOld, res, zBegin, zEnd);
 
-	if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
+	if(DOMAIN_BC_FRONT == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
 	else setZeroY(_yVelocityOld, res, zBegin, zEnd); 
 
-	if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
+	if(DOMAIN_BC_TOP == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
 	else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
 }
 
@@ -1117,10 +1239,10 @@
 	if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
 	else setZeroX(_xVelocityTemp, res, zBegin, zEnd);				
 
-	if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
+	if(DOMAIN_BC_FRONT == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
 	else setZeroY(_yVelocityTemp, res, zBegin, zEnd); 
 
-	if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
+	if(DOMAIN_BC_TOP == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
 	else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
 
 	setZeroBorder(_density, res, zBegin, zEnd);
Index: intern/smoke/intern/FLUID_3D.h
===================================================================
--- intern/smoke/intern/FLUID_3D.h	(revision 30053)
+++ intern/smoke/intern/FLUID_3D.h	(working copy)
@@ -42,11 +42,11 @@
 class FLUID_3D  
 {
 	public:
-		FLUID_3D(int *res, /* int amplify, */ float *p0, float dt);
+		FLUID_3D(int *res, /* int amplify, */ float *p0);
 		FLUID_3D() {};
 		virtual ~FLUID_3D();
 
-		void initBlenderRNA(float *alpha, float *beta);
+		void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
 		
 		// create & allocate vector noise advection 
 		void initVectorNoise(int amplify);
@@ -110,12 +110,26 @@
 
 		// simulation constants
 		float _dt;
+		float *_dt_factor;
 		float _vorticityEps;
 		float _heatDiffusion;
+		float *_vorticityRNA;	// RNA-pointer.
 		float *_alpha; // for the buoyancy density term <-- as pointer to get blender RNA in here
 		float *_beta; // was _buoyancy <-- as pointer to get blender RNA in here
 		float _tempAmb; /* ambient temperature */
+		float _constant_scaling;
 
+		bool DOMAIN_BC_FRONT;  // z
+		bool DOMAIN_BC_TOP;    // y
+		bool DOMAIN_BC_LEFT;   // x
+		bool DOMAIN_BC_BACK;   // DOMAIN_BC_FRONT
+		bool DOMAIN_BC_BOTTOM; // DOMAIN_BC_TOP
+		bool DOMAIN_BC_RIGHT;  // DOMAIN_BC_LEFT
+		int *_border_colli; // border collision rules <-- as pointer to get blender RNA in here
+		int colloPrev;		// To track whether value has been changed (to not
+							// have to recalibrate borders if nothing has changed
+		void setBorderCollisions();
+
 		// WTURBULENCE object, if active
 		// WTURBULENCE* _wTurbulence;
 
Index: intern/smoke/intern/smoke_API.cpp
===================================================================
--- intern/smoke/intern/smoke_API.cpp	(revision 30053)
+++ intern/smoke/intern/smoke_API.cpp	(working copy)
@@ -33,10 +33,10 @@
 #include <math.h>
 
 // y in smoke is z in blender
-extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dt)
+extern "C" FLUID_3D *smoke_init(int *res, float *p0)
 {
 	// smoke lib uses y as top-bottom/vertical axis where blender uses z
-	FLUID_3D *fluid = new FLUID_3D(res, p0, dt);
+	FLUID_3D *fluid = new FLUID_3D(res, p0);
 
 	// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
 
@@ -85,9 +85,9 @@
 	wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); 
 }
 
-extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta)
+extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
 {
-	fluid->initBlenderRNA(alpha, beta);
+	fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
 }
 
 extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
Index: release/scripts/ui/properties_physics_smoke.py
===================================================================
--- release/scripts/ui/properties_physics_smoke.py	(revision 30053)
+++ release/scripts/ui/properties_physics_smoke.py	(working copy)
@@ -80,19 +80,28 @@
                 col.prop(domain, "maxres", text="Divisions")
                 col.label(text="Particle:")
                 col.prop(domain, "initial_velocity", text="Initial Velocity")
+                sub = col.column()
+                sub.active = domain.initial_velocity
+                sub.prop(domain, "velocity_multiplier", text="Multiplier")
 
                 if wide_ui:
                     col = split.column()
                 col.label(text="Behavior:")
                 col.prop(domain, "alpha")
                 col.prop(domain, "beta")
+                col.prop(domain, "vorticity")
+                col.prop(domain, "time_scale")
                 col.prop(domain, "dissolve_smoke", text="Dissolve")
                 sub = col.column()
                 sub.active = domain.dissolve_smoke
                 sub.prop(domain, "dissolve_speed", text="Time")
                 sub.prop(domain, "dissolve_smoke_log", text="Slow")
 
+                layout.label(text="Domain Border Collisions:")
+                layout.prop(domain, "smoke_domain_colli", expand=True)
+
             elif md.smoke_type == 'FLOW':
+
                 flow = md.flow_settings
 
                 split = layout.split()
@@ -111,6 +120,7 @@
                     col.label(text="Behavior:")
                     col.prop(flow, "temperature")
                     col.prop(flow, "density")
+                    col.prop(flow, "absolute")
 
             #elif md.smoke_type == 'COLLISION':
             #	layout.separator()
@@ -191,6 +201,7 @@
         col = split.column()
         col.label(text="Resolution:")
         col.prop(md, "amplify", text="Divisions")
+        col.prop(md, "smoothemitter")
         col.prop(md, "viewhighres")
 
         if wide_ui:
Index: source/blender/blenkernel/intern/smoke.c
===================================================================
--- source/blender/blenkernel/intern/smoke.c	(revision 30053)
+++ source/blender/blenkernel/intern/smoke.c	(working copy)
@@ -220,7 +220,7 @@
 
 		// printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
 		// dt max is 0.1
-		smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1);
+		smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0);
 		smd->time = scene->r.cfra;
 
 		if(smd->domain->flags & MOD_SMOKE_HIGHRES)
@@ -237,7 +237,7 @@
 		if(!smd->domain->shadow)
 			smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");
 
-		smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta));
+		smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->time_scale), &(smd->domain->vorticity), &(smd->domain->border_collisions));
 
 		if(smd->domain->wt)	
 		{
@@ -713,11 +713,16 @@
 			smd->domain->omega = 1.0;			
 			smd->domain->alpha = -0.001;
 			smd->domain->beta = 0.1;
+			smd->domain->time_scale = 1.0;
+			smd->domain->vorticity = 2.0;
+			smd->domain->border_collisions = 1;		// vertically non-colliding
 			smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
 			smd->domain->strength = 2.0;
 			smd->domain->noise = MOD_SMOKE_NOISEWAVE;
 			smd->domain->diss_speed = 5;
-			// init view3d buffer
+			smd->domain->vel_multi = 1.0;
+			// init 3dview buffer
+
 			smd->domain->viewsettings = 0;
 			smd->domain->effector_weights = BKE_add_effector_weights(NULL);
 		}
@@ -733,6 +738,7 @@
 			/* set some standard values */
 			smd->flow->density = 1.0;
 			smd->flow->temp = 1.0;
+			smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE;
 
 			smd->flow->psys = NULL;
 
@@ -862,7 +868,7 @@
 					{
 						ParticleSystem *psys = sfs->psys;
 						ParticleSettings *part=psys->part;
-						ParticleData *pa = NULL;								
+						ParticleData *pa = NULL;							
 						int p = 0;								
 						float *density = smoke_get_density(sds->fluid);								
 						float *bigdensity = smoke_turbulence_get_density(sds->wt);								
@@ -871,7 +877,27 @@
 						float *velocity_y = smoke_get_velocity_y(sds->fluid);								
 						float *velocity_z = smoke_get_velocity_z(sds->fluid);								
 						unsigned char *obstacle = smoke_get_obstacle(sds->fluid);								
-						int bigres[3];	
+						int bigres[3];
+						short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
+						short high_emission_smoothing = (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH);
+
+						/*
+						* A temporary volume map used to store whole emissive
+						* area to be added to smoke density and interpolated
+						* for high resolution smoke.
+						*/
+						float *temp_emission_map = NULL;
+
+						// initialize temp emission map
+						if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
+						{
+							int i;
+							temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission");
+							// set whole volume to 0.0f
+							for (i=0; i<sds->res[0]*sds->res[1]*sds->res[2]; i++) {
+								temp_emission_map[i] = 0.0f;
+							}
+						}
 														
 						// mostly copied from particle code								
 						for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)								
@@ -905,33 +931,21 @@
 								// heat[index] += sfs->temp * 0.1;										
 								// density[index] += sfs->density * 0.1;
 								heat[index] = sfs->temp;
-								density[index] = sfs->density;
+								
+								// Add emitter density to temp emission map
+								temp_emission_map[index] = sfs->density;
 
 
 								// Uses particle velocity as initial velocity for smoke
 								if(smd->domain->flags & MOD_SMOKE_INITVELOCITY) {
-								velocity_x[index] = pa->state.vel[0];
-								velocity_y[index] = pa->state.vel[1];
-								velocity_z[index] = pa->state.vel[2];										
+
+									velocity_x[index] = pa->state.vel[0]*smd->domain->vel_multi;
+									velocity_y[index] = pa->state.vel[1]*smd->domain->vel_multi;
+									velocity_z[index] = pa->state.vel[2]*smd->domain->vel_multi;
+
 								}										
-								
-								// obstacle[index] |= 2;
-								// we need different handling for the high-res feature
-								if(bigdensity)
-								{
-									// init all surrounding cells according to amplification, too
-									int i, j, k;
+							
 
-									smoke_turbulence_get_res(smd->domain->wt, bigres);
-
-									for(i = 0; i < smd->domain->amplify + 1; i++)
-										for(j = 0; j < smd->domain->amplify + 1; j++)
-											for(k = 0; k < smd->domain->amplify + 1; k++)													
-											{														
-												index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k);														
-												bigdensity[index] = sfs->density;													
-											}										
-								}									
 							}									
 							else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow									
 							{										
@@ -954,9 +968,136 @@
 												index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k);														
 												bigdensity[index] = 0.f;													
 											}										
-								}									
-							}	// particles loop							
-					}							
+								}
+							}
+							}	// particles loop
+
+
+							// apply emission values
+							if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) {
+
+								// initialize variables
+								int ii, jj, kk, x, y, z, block_size;
+								size_t index, index_big;
+
+								smoke_turbulence_get_res(smd->domain->wt, bigres);
+								block_size = smd->domain->amplify + 1;	// high res block size
+
+
+									// loop through every low res cell
+									for(x = 0; x < sds->res[0]; x++)
+										for(y = 0; y < sds->res[1]; y++)
+											for(z = 0; z < sds->res[2]; z++)													
+											{
+
+												// neighbour cell emission densities (for high resolution smoke smooth interpolation)
+												float c000, c001, c010, c011,  c100, c101, c110, c111;
+
+												c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0;
+												c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0;
+												c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0;
+												c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0;
+
+												c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0;
+												c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0;
+												c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0;
+												c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)];			// this cell
+
+
+
+												// get cell index
+												index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
+
+												// add emission to low resolution density
+												if (absolute_flow) {if (temp_emission_map[index]>0) density[index] = temp_emission_map[index];}
+												else {
+													density[index] += temp_emission_map[index];
+													if (density[index]>1) density[index]=1.0f;
+												}
+
+												smoke_turbulence_get_res(smd->domain->wt, bigres);
+
+
+
+												/*
+												loop through high res blocks if high res enabled
+												*/
+												if (bigdensity)
+												for(ii = 0; ii < block_size; ii++)
+													for(jj = 0; jj < block_size; jj++)
+														for(kk = 0; kk < block_size; kk++)													
+														{
+
+														float fx,fy,fz, interpolated_value;
+														int shift_x, shift_y, shift_z;
+
+
+														/*
+														* Do volume interpolation if emitter smoothing
+														* is enabled
+														*/
+														if (high_emission_smoothing) {
+															// convert block position to relative
+															// for interpolation smoothing
+															fx = (float)ii/block_size + 0.5f/block_size;
+															fy = (float)jj/block_size + 0.5f/block_size;
+															fz = (float)kk/block_size + 0.5f/block_size;
+
+															// calculate trilinear interpolation
+															interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) +
+															c100 * fx * (1-fy) * (1-fz) +
+															c010 * (1-fx) * fy * (1-fz) +
+															c001 * (1-fx) * (1-fy) * fz +
+															c101 * fx * (1-fy) * fz +
+															c011 * (1-fx) * fy * fz +
+															c110 * fx * fy * (1-fz) +
+															c111 * fx * fy * fz;
+
+
+															// add some contrast / sharpness
+															// depending on hi-res block size
+
+															interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density;
+															if (interpolated_value<0.0f) interpolated_value = 0.0f;
+															if (interpolated_value>1.0f) interpolated_value = 1.0f;
+
+															// shift smoke block index
+															// (because pixel center is actually
+															// in halfway of the low res block)
+															shift_x = (x < 1) ? 0 : block_size/2;
+															shift_y = (y < 1) ? 0 : block_size/2;
+															shift_z = (z < 1) ? 0 : block_size/2;
+														}
+														else {
+															// without interpolation use same low resolution
+															// block value for all hi-res blocks
+															interpolated_value = c111;
+															shift_x = 0;
+															shift_y = 0;
+															shift_z = 0;
+														}
+
+														// get shifted index for current high resolution block
+														index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z);														
+														
+														// add emission data to high resolution density
+														if (absolute_flow) {if (interpolated_value > 0) bigdensity[index_big] = interpolated_value;}
+														else {
+															bigdensity[index_big] += interpolated_value;
+															if (bigdensity[index_big]>1) bigdensity[index_big]=1.0f;
+														}
+
+														} // end of hires loop
+
+									}	// end of low res loop
+
+								// free temporary emission map
+							if (temp_emission_map) MEM_freeN(temp_emission_map);
+
+							}	// end emission
+
+
+										
 				}							
 				else							
 				{								
@@ -970,7 +1111,7 @@
 
 						BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh);
 					}*/							
-				}						
+				}
 			}						
 		}
 			if(sds->fluid_group)
Index: source/blender/makesdna/DNA_smoke_types.h
===================================================================
--- source/blender/makesdna/DNA_smoke_types.h	(revision 30053)
+++ source/blender/makesdna/DNA_smoke_types.h	(working copy)
@@ -35,6 +35,7 @@
 #define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */
 #define MOD_SMOKE_INITVELOCITY (1<<4) /* passes particles speed to
 										 the smoke*/
+#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* smoothens high res emission*/
 
 /* noise */
 #define MOD_SMOKE_NOISEWAVE (1<<0)
@@ -47,6 +48,11 @@
 #define SM_CACHE_LIGHT		0
 #define SM_CACHE_HEAVY		1
 
+/* domain border collision */
+#define SM_BORDER_OPEN		0
+#define SM_BORDER_VERTICAL	1
+#define SM_BORDER_CLOSED	2
+
 typedef struct SmokeDomainSettings {
 	struct SmokeModifierData *smd; /* for fast RNA access */
 	struct FLUID_3D *fluid;
@@ -84,6 +90,11 @@
 	struct PointCache *point_cache[2];	/* definition is in DNA_object_force.h */
 	struct ListBase ptcaches[2];
 	struct EffectorWeights *effector_weights;
+	int border_collisions;	/* How domain border collisions are handled */
+	float vel_multi;				// Multiplier for particle velocity
+	float time_scale;
+	float vorticity;
+
 } SmokeDomainSettings;
 
 
@@ -91,7 +102,10 @@
 
 /* type */
 #define MOD_SMOKE_FLOW_TYPE_OUTFLOW (1<<1)
+#define MOD_SMOKE_FLOW_ABSOLUTE (1<<1) /*old style emission*/
 
+
+
 typedef struct SmokeFlowSettings {
 	struct SmokeModifierData *smd; /* for fast RNA access */
 	struct ParticleSystem *psys;
@@ -103,7 +117,7 @@
 	short vgroup_density;
 	short vgroup_heat;
 	short type; /* inflow =0 or outflow = 1 */
-	int pad;
+	int flags; /* absolute emission etc*/
 } SmokeFlowSettings;
 
 /*
Index: source/blender/makesrna/intern/rna_smoke.c
===================================================================
--- source/blender/makesrna/intern/rna_smoke.c	(revision 30053)
+++ source/blender/makesrna/intern/rna_smoke.c	(working copy)
@@ -120,6 +120,12 @@
 		{SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
 		{0, NULL, 0, NULL, NULL}};
 
+	static EnumPropertyItem smoke_domain_colli_items[] = {
+		{SM_BORDER_OPEN, "BORDEROPEN", 0, "Open", "Smoke doesn't collide with any border"},
+		{SM_BORDER_VERTICAL, "BORDERVERTICAL", 0, "Vertically Open", "Smoke doesn't collide with top and bottom sides"},
+		{SM_BORDER_CLOSED, "BORDERCLOSED", 0, "Collide All", "Smoke collides with every side"},
+		{0, NULL, 0, NULL, NULL}};
+
 	srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
 	RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings");
 	RNA_def_struct_sdna(srna, "SmokeDomainSettings");
@@ -192,8 +198,8 @@
 
 	prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "strength");
-	RNA_def_property_range(prop, 1.0, 10.0);
-	RNA_def_property_ui_range(prop, 1.0, 10.0, 1, 2);
+	RNA_def_property_range(prop, 0.0, 10.0);
+	RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
 	RNA_def_property_ui_text(prop, "Strength", "Strength of wavelet noise");
 	RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
 
@@ -209,6 +215,13 @@
 	RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits it's velocity from the emitter particle");
 	RNA_def_property_update(prop, 0, NULL);
 
+	prop= RNA_def_property(srna, "velocity_multiplier", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "vel_multi");
+	RNA_def_property_range(prop, -2.0, 2.0);
+	RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
+	RNA_def_property_ui_text(prop, "Multiplier", "Multiplier to adjust velocity passed to smoke");
+	RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
 	prop= RNA_def_property(srna, "dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
 	RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
@@ -241,12 +254,37 @@
 	RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
 	RNA_def_property_update(prop, 0, NULL);
 
+	prop= RNA_def_property(srna, "smoke_domain_colli", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "border_collisions");
+	RNA_def_property_enum_items(prop, smoke_domain_colli_items);
+	RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
+	RNA_def_property_update(prop, 0, NULL);
 
+
 	prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
 	RNA_def_property_struct_type(prop, "EffectorWeights");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_ui_text(prop, "Effector Weights", "");
 
+	prop= RNA_def_property(srna, "smoothemitter", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH);
+	RNA_def_property_ui_text(prop, "Smooth Emitter", "Smoothens emitted smoke to avoid blockiness.");
+	RNA_def_property_update(prop, 0, NULL);
+
+	prop= RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "time_scale");
+	RNA_def_property_range(prop, 0.2, 1.5);
+	RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5);
+	RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
+	prop= RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "vorticity");
+	RNA_def_property_range(prop, 0.01, 4.0);
+	RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5);
+	RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
 }
 
 static void rna_def_smoke_flow_settings(BlenderRNA *brna)
@@ -284,6 +322,11 @@
 	RNA_def_property_boolean_sdna(prop, NULL, "type", MOD_SMOKE_FLOW_TYPE_OUTFLOW);
 	RNA_def_property_ui_text(prop, "Outflow", "Deletes smoke from simulation");
 	RNA_def_property_update(prop, 0, NULL);
+
+	prop= RNA_def_property(srna, "absolute", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_ABSOLUTE);
+	RNA_def_property_ui_text(prop, "Absolute Density", "Only allows given density value in emitter area.");
+	RNA_def_property_update(prop, 0, NULL);
 }
 
 static void rna_def_smoke_coll_settings(BlenderRNA *brna)
