Browse Source

Fix line and shape segment counts and smooth line antialiasing when love.graphics.applyTransform and replaceTransform are used.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
92774b759b

+ 6 - 0
src/common/Matrix.cpp

@@ -149,6 +149,12 @@ void Matrix4::setShear(float kx, float ky)
 	e[1] = ky;
 	e[1] = ky;
 	e[4] = kx;
 	e[4] = kx;
 }
 }
+
+void Matrix4::getApproximateScale(float &sx, float &sy) const
+{
+	sx = sqrtf(e[0] * e[0] + e[4] * e[4]);
+	sy = sqrtf(e[1] * e[1] + e[5] * e[5]);
+}
 	
 	
 void Matrix4::setRawTransformation(float t00, float t10, float t01, float t11, float x, float y)
 void Matrix4::setRawTransformation(float t00, float t10, float t01, float t11, float x, float y)
 {
 {

+ 6 - 0
src/common/Matrix.h

@@ -118,6 +118,12 @@ public:
 	 * @param ky Shear along y-axis.
 	 * @param ky Shear along y-axis.
 	 **/
 	 **/
 	void setShear(float kx, float ky);
 	void setShear(float kx, float ky);
+
+	/**
+	 * Calculates the scale factors for a 2D affine transform. The output values
+	 * are absolute (not signed).
+	 **/
+	void getApproximateScale(float &sx, float &sy) const;
 	
 	
 	/**
 	/**
 	 * Sets a transformation's values directly. Useful if you want to modify them inplace,
 	 * Sets a transformation's values directly. Useful if you want to modify them inplace,

+ 24 - 14
src/modules/graphics/opengl/Graphics.cpp

@@ -291,9 +291,9 @@ bool Graphics::setMode(int width, int height)
 	// Restore the graphics state.
 	// Restore the graphics state.
 	restoreState(states.back());
 	restoreState(states.back());
 
 
-	pixelSizeStack.clear();
-	pixelSizeStack.reserve(5);
-	pixelSizeStack.push_back(1);
+	pixelScaleStack.clear();
+	pixelScaleStack.reserve(5);
+	pixelScaleStack.push_back(1);
 
 
 	int gammacorrect = isGammaCorrect() ? 1 : 0;
 	int gammacorrect = isGammaCorrect() ? 1 : 0;
 
 
@@ -1688,23 +1688,24 @@ void Graphics::polyline(const float *coords, size_t count)
 		throw RenderOutsidePassException();
 		throw RenderOutsidePassException();
 
 
 	const DisplayState &state = states.back();
 	const DisplayState &state = states.back();
+	float pixelsize = std::max((float) pixelScaleStack.back(), 0.000001f);
 
 
 	if (state.lineJoin == LINE_JOIN_NONE)
 	if (state.lineJoin == LINE_JOIN_NONE)
 	{
 	{
 		NoneJoinPolyline line;
 		NoneJoinPolyline line;
-		line.render(coords, count, state.lineWidth * .5f, float(pixelSizeStack.back()), state.lineStyle == LINE_SMOOTH);
+		line.render(coords, count, state.lineWidth * .5f, pixelsize, state.lineStyle == LINE_SMOOTH);
 		line.draw();
 		line.draw();
 	}
 	}
 	else if (state.lineJoin == LINE_JOIN_BEVEL)
 	else if (state.lineJoin == LINE_JOIN_BEVEL)
 	{
 	{
 		BevelJoinPolyline line;
 		BevelJoinPolyline line;
-		line.render(coords, count, state.lineWidth * .5f, float(pixelSizeStack.back()), state.lineStyle == LINE_SMOOTH);
+		line.render(coords, count, state.lineWidth * .5f, pixelsize, state.lineStyle == LINE_SMOOTH);
 		line.draw();
 		line.draw();
 	}
 	}
 	else // LINE_JOIN_MITER
 	else // LINE_JOIN_MITER
 	{
 	{
 		MiterJoinPolyline line;
 		MiterJoinPolyline line;
-		line.render(coords, count, state.lineWidth * .5f, float(pixelSizeStack.back()), state.lineStyle == LINE_SMOOTH);
+		line.render(coords, count, state.lineWidth * .5f, pixelsize, state.lineStyle == LINE_SMOOTH);
 		line.draw();
 		line.draw();
 	}
 	}
 }
 }
@@ -1782,8 +1783,7 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, floa
 
 
 int Graphics::calculateEllipsePoints(float rx, float ry) const
 int Graphics::calculateEllipsePoints(float rx, float ry) const
 {
 {
-	float pixelScale = 1.0f / std::max((float) pixelSizeStack.back(), 0.00001f);
-	int points = (int) sqrtf(((rx + ry) / 2.0f) * 20.0f * pixelScale);
+	int points = (int) sqrtf(((rx + ry) / 2.0f) * 20.0f * (float) pixelScaleStack.back());
 	return std::max(points, 8);
 	return std::max(points, 8);
 }
 }
 
 
@@ -2042,7 +2042,7 @@ void Graphics::push(StackType type)
 
 
 	gl.pushTransform();
 	gl.pushTransform();
 
 
-	pixelSizeStack.push_back(pixelSizeStack.back());
+	pixelScaleStack.push_back(pixelScaleStack.back());
 
 
 	if (type == STACK_ALL)
 	if (type == STACK_ALL)
 		states.push_back(states.back());
 		states.push_back(states.back());
@@ -2056,7 +2056,7 @@ void Graphics::pop()
 		throw Exception("Minimum stack depth reached (more pops than pushes?)");
 		throw Exception("Minimum stack depth reached (more pops than pushes?)");
 
 
 	gl.popTransform();
 	gl.popTransform();
-	pixelSizeStack.pop_back();
+	pixelScaleStack.pop_back();
 
 
 	if (stackTypes.back() == STACK_ALL)
 	if (stackTypes.back() == STACK_ALL)
 	{
 	{
@@ -2079,7 +2079,7 @@ void Graphics::rotate(float r)
 void Graphics::scale(float x, float y)
 void Graphics::scale(float x, float y)
 {
 {
 	gl.getTransform().scale(x, y);
 	gl.getTransform().scale(x, y);
-	pixelSizeStack.back() *= 2. / (fabs(x) + fabs(y));
+	pixelScaleStack.back() *= (fabs(x) + fabs(y)) / 2.0;
 }
 }
 
 
 void Graphics::translate(float x, float y)
 void Graphics::translate(float x, float y)
@@ -2095,17 +2095,27 @@ void Graphics::shear(float kx, float ky)
 void Graphics::origin()
 void Graphics::origin()
 {
 {
 	gl.getTransform().setIdentity();
 	gl.getTransform().setIdentity();
-	pixelSizeStack.back() = 1;
+	pixelScaleStack.back() = 1;
 }
 }
 
 
 void Graphics::applyTransform(love::math::Transform *transform)
 void Graphics::applyTransform(love::math::Transform *transform)
 {
 {
-	gl.getTransform() *= transform->getMatrix();
+	Matrix4 &m = gl.getTransform();
+	m *= transform->getMatrix();
+
+	float sx, sy;
+	m.getApproximateScale(sx, sy);
+	pixelScaleStack.back() = (sx + sy) / 2.0;
 }
 }
 
 
 void Graphics::replaceTransform(love::math::Transform *transform)
 void Graphics::replaceTransform(love::math::Transform *transform)
 {
 {
-	gl.getTransform() = transform->getMatrix();
+	const Matrix4 &m = transform->getMatrix();
+	gl.getTransform() = m;
+
+	float sx, sy;
+	m.getApproximateScale(sx, sy);
+	pixelScaleStack.back() = (sx + sy) / 2.0;
 }
 }
 
 
 Vector Graphics::transformPoint(Vector point)
 Vector Graphics::transformPoint(Vector point)

+ 1 - 1
src/modules/graphics/opengl/Graphics.h

@@ -567,7 +567,7 @@ private:
 
 
 	StrongRef<Font> defaultFont;
 	StrongRef<Font> defaultFont;
 
 
-	std::vector<double> pixelSizeStack; // stores current size of a pixel (needed for line drawing)
+	std::vector<double> pixelScaleStack;
 
 
 	std::vector<ScreenshotInfo> pendingScreenshotCallbacks;
 	std::vector<ScreenshotInfo> pendingScreenshotCallbacks;