Browse Source

Fixed Geometry texture coordinates when using Geometry to draw auto-padded NPOT images (resolves issue #696)

Alex Szpakowski 12 years ago
parent
commit
2128ba321e

+ 31 - 1
src/modules/graphics/opengl/Image.cpp

@@ -112,6 +112,11 @@ void Image::drawg(love::graphics::Geometry *geom, float x, float y, float angle,
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
 
 	const vertex *v = geom->getVertexArray();
 	const vertex *v = geom->getVertexArray();
+	size_t vertcount = geom->getVertexCount();
+
+	// Padded NPOT images require texture coordinate scaling with Geometry.
+	if (!hasNpot())
+		v = scaleNPOT(v, vertcount);
 
 
 	// use colors stored in geometry (horrible, horrible hack)
 	// use colors stored in geometry (horrible, horrible hack)
 	if (geom->hasVertexColors())
 	if (geom->hasVertexColors())
@@ -135,13 +140,17 @@ void Image::drawg(love::graphics::Geometry *geom, float x, float y, float angle,
 		break;
 		break;
 	}
 	}
 
 
-	drawv(t, v, geom->getVertexCount(), glmode, geom->getElementArray(), geom->getElementCount());
+	drawv(t, v, vertcount, glmode, geom->getElementArray(), geom->getElementCount());
 
 
 	if (geom->hasVertexColors())
 	if (geom->hasVertexColors())
 	{
 	{
 		glDisableClientState(GL_COLOR_ARRAY);
 		glDisableClientState(GL_COLOR_ARRAY);
 		gl.setColor(gl.getColor());
 		gl.setColor(gl.getColor());
 	}
 	}
+
+	// If we made new verts with scaled texcoords then we should clean them up.
+	if (!hasNpot())
+		delete[] v;
 }
 }
 
 
 void Image::uploadCompressedMipmaps()
 void Image::uploadCompressedMipmaps()
@@ -551,6 +560,27 @@ bool Image::refresh()
 	return true;
 	return true;
 }
 }
 
 
+love::Vector Image::getTexCoordScale() const
+{
+	// FIXME: this should be changed if Image::loadVolatilePOT changes.
+	return love::Vector(vertices[2].s, vertices[2].t);
+}
+
+vertex *Image::scaleNPOT(const love::vertex *v, size_t count) const
+{
+	vertex *newverts = new vertex[count];
+	love::Vector scale = getTexCoordScale();
+
+	for (size_t i = 0; i < count; i++)
+	{
+		newverts[i] = v[i];
+		newverts[i].s *= scale.x;
+		newverts[i].t *= scale.y;
+	}
+
+	return newverts;
+}
+
 void Image::drawv(const Matrix &t, const vertex *v, GLsizei count, GLenum mode, const uint16 *e, GLsizei ecount) const
 void Image::drawv(const Matrix &t, const vertex *v, GLsizei count, GLenum mode, const uint16 *e, GLsizei ecount) const
 {
 {
 	bind();
 	bind();

+ 9 - 1
src/modules/graphics/opengl/Image.h

@@ -22,9 +22,10 @@
 #define LOVE_GRAPHICS_OPENGL_IMAGE_H
 #define LOVE_GRAPHICS_OPENGL_IMAGE_H
 
 
 // LOVE
 // LOVE
+#include "common/config.h"
 #include "common/Matrix.h"
 #include "common/Matrix.h"
+#include "common/Vector.h"
 #include "common/math.h"
 #include "common/math.h"
-#include "common/config.h"
 #include "image/ImageData.h"
 #include "image/ImageData.h"
 #include "image/CompressedData.h"
 #include "image/CompressedData.h"
 #include "graphics/Image.h"
 #include "graphics/Image.h"
@@ -123,6 +124,12 @@ public:
 	 **/
 	 **/
 	bool refresh();
 	bool refresh();
 
 
+	/**
+	 * Gets the texture coordinate scale used for drawing auto-padded NPOT
+	 * images correctly.
+	 **/
+	love::Vector getTexCoordScale() const;
+
 	static void setDefaultMipmapSharpness(float sharpness);
 	static void setDefaultMipmapSharpness(float sharpness);
 	static float getDefaultMipmapSharpness();
 	static float getDefaultMipmapSharpness();
 	static void setDefaultMipmapFilter(FilterMode f);
 	static void setDefaultMipmapFilter(FilterMode f);
@@ -138,6 +145,7 @@ public:
 
 
 private:
 private:
 
 
+	vertex *scaleNPOT(const vertex *v, size_t count) const;
 	void drawv(const Matrix &t, const vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
 	void drawv(const Matrix &t, const vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
 
 
 	friend class Shader;
 	friend class Shader;

+ 23 - 0
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -114,6 +114,9 @@ int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, fl
 	if (color)
 	if (color)
 		setColorv(sprite, *color);
 		setColorv(sprite, *color);
 
 
+	// Auto-padded NPOT images require texcoord scaling for their vertices.
+	scaleNPOT(sprite, 4);
+
 	addv(sprite, (index == -1) ? next : index);
 	addv(sprite, (index == -1) ? next : index);
 
 
 	// Increment counter.
 	// Increment counter.
@@ -158,6 +161,9 @@ int SpriteBatch::addg(Geometry *geom, float x, float y, float a, float sx, float
 	if (color && !geom->hasVertexColors())
 	if (color && !geom->hasVertexColors())
 		setColorv(sprite, *color);
 		setColorv(sprite, *color);
 
 
+	// Auto-padded NPOT images require texcoord scaling for their vertices.
+	scaleNPOT(sprite, 4);
+
 	addv(sprite, (index == -1) ? next : index);
 	addv(sprite, (index == -1) ? next : index);
 
 
 	// Make sure SpriteBatch colors are enabled if the Geometry has custom colors.
 	// Make sure SpriteBatch colors are enabled if the Geometry has custom colors.
@@ -334,6 +340,23 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float
 	glPopMatrix();
 	glPopMatrix();
 }
 }
 
 
+void SpriteBatch::scaleNPOT(vertex *v, size_t count)
+{
+	if (Image::hasNpot())
+		return;
+
+	love::Vector scale = image->getTexCoordScale();
+
+	if (scale.x == 1.0f && scale.y == 1.0f)
+		return;
+
+	for (size_t i = 0; i < count; i++)
+	{
+		v[i].s *= scale.x;
+		v[i].t *= scale.y;
+	}
+}
+
 void SpriteBatch::addv(const vertex *v, int index)
 void SpriteBatch::addv(const vertex *v, int index)
 {
 {
 	static const int sprite_size = 4 * sizeof(vertex); // bytecount
 	static const int sprite_size = 4 * sizeof(vertex); // bytecount

+ 2 - 0
src/modules/graphics/opengl/SpriteBatch.h

@@ -116,6 +116,8 @@ public:
 
 
 private:
 private:
 
 
+	void scaleNPOT(vertex *v, size_t count);
+
 	void addv(const vertex *v, int index);
 	void addv(const vertex *v, int index);
 
 
 	/**
 	/**