[Bf-blender-cvs] [9c883a1] master: Fix T38011 and cleanup of Lens Distortion node code.

Lukas Tönne noreply at git.blender.org
Wed Jan 22 14:42:15 CET 2014


Commit: 9c883a1ecabe387533909b1e3116c2c30418f6e9
Author: Lukas Tönne
Date:   Wed Jan 22 14:32:21 2014 +0100
https://developer.blender.org/rB9c883a1ecabe387533909b1e3116c2c30418f6e9

Fix T38011 and cleanup of Lens Distortion node code.

The area-of-interest calculation for that node didn't work reliably.
It tries to estimate the distorted rectangular area based on min/max
distortion and dispersion values, but this fails in some cases and
leaves uninitialized buffer chunks. So now simply use the full input
rect as the area, even though it may not be as efficient - at least it
works ...

Also cleaned up the code somewhat to make it understandable, using
separate functions for common stuff instead of cryptic walls of math.

===================================================================

M	source/blender/compositor/nodes/COM_LensDistortionNode.cpp
M	source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
M	source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
M	source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h

===================================================================

diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
index f91744d..9af1fce 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
@@ -41,21 +41,20 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC
 		this->getInputSocket(2)->relinkConnections(operation->getInputSocket(1), 2, graph);
 		this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
 
-		operation->setData(data);
 		graph->addOperation(operation);
 
 	}
 	else {
 		ScreenLensDistortionOperation *operation = new ScreenLensDistortionOperation();
 		operation->setbNode(editorNode);
-		operation->setData(data);
-		if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected())) {
-			// no nodes connected to the distortion and dispersion. We can precalculate some values
-			float distortion = this->getInputSocket(1)->getEditorValueFloat();
-			float dispersion = this->getInputSocket(2)->getEditorValueFloat();
-			operation->setDistortionAndDispersion(distortion, dispersion);
-		}
+		operation->setFit(data->fit);
+		operation->setJitter(data->jit);
 
+		if (!getInputSocket(1)->isConnected())
+			operation->setDistortion(getInputSocket(1)->getEditorValueFloat());
+		if (!getInputSocket(2)->isConnected())
+			operation->setDispersion(getInputSocket(2)->getEditorValueFloat());
+		
 		this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
 		this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
 		this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph);
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
index 3c91081..fc9c760 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
@@ -32,8 +32,6 @@ private:
 	 */
 	SocketReader *m_inputProgram;
 	
-	NodeLensDist *m_data;
-	
 	float m_dispersion;
 	bool m_dispersionAvailable;
 	
@@ -57,8 +55,6 @@ public:
 	 */
 	void deinitExecution();
 	
-	void setData(NodeLensDist *data) { this->m_data = data; }
-	
 	bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
 
 	void updateDispersion();
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
index 29c104d..035789e 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
@@ -36,101 +36,149 @@ ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation()
 	this->addOutputSocket(COM_DT_COLOR);
 	this->setComplex(true);
 	this->m_inputProgram = NULL;
-	this->m_valuesAvailable = false;
-	this->m_dispersion = 0.0f;
 	this->m_distortion = 0.0f;
+	this->m_dispersion = 0.0f;
+	this->m_distortion_const = false;
+	this->m_dispersion_const = false;
+	this->m_variables_ready = false;
+}
+
+void ScreenLensDistortionOperation::setDistortion(float distortion)
+{
+	m_distortion = distortion;
+	m_distortion_const = true;
 }
+
+void ScreenLensDistortionOperation::setDispersion(float dispersion)
+{
+	m_dispersion = dispersion;
+	m_dispersion_const = true;
+}
+
 void ScreenLensDistortionOperation::initExecution()
 {
 	this->m_inputProgram = this->getInputSocketReader(0);
 	this->initMutex();
+	
 	this->m_cx = 0.5f * (float)getWidth();
 	this->m_cy = 0.5f * (float)getHeight();
 	
+	/* if both are constant, init variables once */
+	if (m_distortion_const && m_dispersion_const) {
+		updateVariables(m_distortion, m_dispersion);
+		m_variables_ready = true;
+	}
 }
 
 void *ScreenLensDistortionOperation::initializeTileData(rcti *rect)
 {
 	void *buffer = this->m_inputProgram->initializeTileData(NULL);
-	updateDispersionAndDistortion();
+
+	/* get distortion/dispersion values once, by reading inputs at (0,0)
+	 * XXX this assumes invariable values (no image inputs),
+	 * we don't have a nice generic system for that yet
+	 */
+	if (!m_variables_ready) {
+		this->lockMutex();
+		
+		if (!m_distortion_const) {
+			float result[4];
+			getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST);
+			m_distortion = result[0];
+		}
+		if (!m_dispersion_const) {
+			float result[4];
+			getInputSocketReader(2)->readSampled(result, 0, 0, COM_PS_NEAREST);
+			m_dispersion = result[0];
+		}
+		
+		updateVariables(m_distortion, m_dispersion);
+		m_variables_ready = true;
+		
+		this->unlockMutex();
+	}
+	
 	return buffer;
 }
 
-void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, void *data)
+void ScreenLensDistortionOperation::get_uv(const float xy[2], float uv[2]) const
 {
-	const float height = this->getHeight();
-	const float width = this->getWidth();
-	MemoryBuffer *buffer = (MemoryBuffer *)data;
+	uv[0] = m_sc * ((xy[0] + 0.5f) - m_cx) / m_cx;
+	uv[1] = m_sc * ((xy[1] + 0.5f) - m_cy) / m_cy;
+}
 
-	int dr = 0, dg = 0, db = 0;
-	float d, t, ln[6] = {0, 0, 0, 0, 0, 0};
-	float tc[4] = {0, 0, 0, 0};
-	const float v = this->m_sc * ((y + 0.5f) - this->m_cy) / this->m_cy;
-	const float u = this->m_sc * ((x + 0.5f) - this->m_cx) / this->m_cx;
-	const float uv_dot = u * u + v * v;
-	int sta = 0, mid = 0, end = 0;
-
-	if ((t = 1.0f - this->m_kr4 * uv_dot) >= 0.0f) {
-		d = 1.0f / (1.0f + sqrtf(t));
-		ln[0] = (u * d + 0.5f) * width - 0.5f, ln[1] = (v * d + 0.5f) * height - 0.5f;
-		sta = 1;
-	}
-	if ((t = 1.0f - this->m_kg4 * uv_dot) >= 0.0f) {
-		d = 1.0f / (1.0f + sqrtf(t));
-		ln[2] = (u * d + 0.5f) * width - 0.5f, ln[3] = (v * d + 0.5f) * height - 0.5f;
-		mid = 1;
+void ScreenLensDistortionOperation::distort_uv(const float uv[2], float t, float xy[2]) const
+{
+	float d = 1.0f / (1.0f + sqrtf(t));
+	xy[0] = (uv[0] * d + 0.5f) * getWidth() - 0.5f;
+	xy[1] = (uv[1] * d + 0.5f) * getHeight() - 0.5f;
+}
+
+bool ScreenLensDistortionOperation::get_delta(float r_sq, float k4, const float uv[2], float delta[2]) const
+{
+	float t = 1.0f - k4 * r_sq;
+	if (t >= 0.0f) {
+		distort_uv(uv, t, delta);
+		return true;
 	}
-	if ((t = 1.0f - this->m_kb4 * uv_dot) >= 0.0f) {
-		d = 1.0f / (1.0f + sqrtf(t));
-		ln[4] = (u * d + 0.5f) * width - 0.5f, ln[5] = (v * d + 0.5f) * height - 0.5f;
-		end = 1;
+	else
+		return false;
+	
+}
+
+void ScreenLensDistortionOperation::accumulate(MemoryBuffer *buffer,
+                                               int a, int b,
+                                               float r_sq, const float uv[2],
+                                               const float delta[3][2],
+                                               float sum[4], int count[3]) const
+{
+	float color[4];
+	
+	float dsf = len_v2v2(delta[a], delta[b]) + 1.0f;
+	int ds = m_jitter ? (dsf < 4.0f ? 2 : (int)sqrtf(dsf)) : (int)dsf;
+	float sd = 1.0f / (float)ds;
+
+	float k4 = m_k4[a];
+	float dk4 = m_dk4[a];
+
+	for (float z = 0; z < ds; ++z) {
+		float tz = (z + (m_jitter ? BLI_frand() : 0.5f)) * sd;
+		float t = 1.0f - (k4 + tz * dk4) * r_sq;
+		
+		float xy[2];
+		distort_uv(uv, t, xy);
+		buffer->readBilinear(color, xy[0], xy[1]);
+		
+		sum[a] += (1.0f - tz) * color[a], sum[b] += tz * color[b];
+		++count[a];
+		++count[b];
 	}
+}
 
-	if (sta && mid && end) {
-		float jit = this->m_data->jit;
-		float z;
-		float color[4];
-		{
-			// RG
-			const int dx = ln[2] - ln[0], dy = ln[3] - ln[1];
-			const float dsf = sqrtf((float)dx * dx + dy * dy) + 1.0f;
-			const int ds = (int)(jit ? ((dsf < 4.0f) ? 2.0f : sqrtf(dsf)) : dsf);
-			const float sd = 1.0f / (float)ds;
-
-			for (z = 0; z < ds; ++z) {
-				const float tz = (z + (jit ? BLI_frand() : 0.5f)) * sd;
-				t = 1.0f - (this->m_kr4 + tz * this->m_drg) * uv_dot;
-				d = 1.0f / (1.0f + sqrtf(t));
-				const float nx = (u * d + 0.5f) * width - 0.5f;
-				const float ny = (v * d + 0.5f) * height - 0.5f;
-				buffer->readBilinear(color, nx, ny);
-				tc[0] += (1.0f - tz) * color[0], tc[1] += tz * color[1];
-				dr++, dg++;
-			}
-		}
-		{
-			// GB
-			const int dx = ln[4] - ln[2], dy = ln[5] - ln[3];
-			const float dsf = sqrtf((float)dx * dx + dy * dy) + 1.0f;
-			const int ds = (int)(jit ? ((dsf < 4.0f) ? 2.0f : sqrtf(dsf)) : dsf);
-			const float sd = 1.0f / (float)ds;
-
-			for (z = 0; z < ds; ++z) {
-				const float tz = (z + (jit ? BLI_frand() : 0.5f)) * sd;
-				t = 1.0f - (this->m_kg4 + tz * this->m_dgb) * uv_dot;
-				d = 1.0f / (1.0f + sqrtf(t));
-				const float nx = (u * d + 0.5f) * width - 0.5f;
-				const float ny = (v * d + 0.5f) * height - 0.5f;
-				buffer->readBilinear(color, nx, ny);
-				tc[1] += (1.0f - tz) * color[1], tc[2] += tz * color[2];
-				dg++, db++;
-			}
+void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, void *data)
+{
+	MemoryBuffer *buffer = (MemoryBuffer *)data;
+	float xy[2] = { (float)x, (float)y };
+	float uv[2];
+	get_uv(xy, uv);
+	float uv_dot = len_squared_v2(uv);
 
-		}
-		if (dr) output[0] = 2.0f * tc[0] / (float)dr;
-		if (dg) output[1] = 2.0f * tc[1] / (float)dg;
-		if (db) output[2] = 2.0f * tc[2] / (float)db;
+	int count[3] = { 0, 0, 0 };
+	float delta[3][2];
+	float sum[4] = { 0, 0, 0, 0 };
 
+	bool valid_r = get_delta(uv_dot, m_k4[0], uv, delta[0]);
+	bool valid_g = get_delta(uv_dot, m_k4[1], uv, delta[1]);
+	bool valid_b = get_delta(uv_dot, m_k4[2], uv, delta[2]);
+
+	if (valid_r && valid_g && valid_b) {
+		accumulate(buffer, 0, 1, uv_dot, uv, delta, sum, count);
+		accumulate(buffer, 1, 2, uv_dot, uv, delta, sum, count);
+		
+		if (count[0]) output[0] = 2.0f * sum[0] / (float)count[0];
+		if (count[1]) output[1] = 2.0f * sum[1] / (float)count[1];
+		if (count[2]) output[2] = 2.0f * sum[2] / (float)count[2];
+		
 		/* set alpha */
 		output[3] = 1.0f;
 	}
@@ -145,44 +193,19 @@ void ScreenLensDistortionOperation::deinitExecution()
 	this->m_inputProgram = NULL;
 }
 
-void ScreenLensDistortionOperation::determineUV(float result[6], float x, float y, float dist

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list