From 9d2fdc00a0a83571783eaa269d92eaa132815201 Mon Sep 17 00:00:00 2001 From: gered Date: Mon, 1 Jul 2013 18:33:30 -0400 Subject: [PATCH] add 3d projected coordinate support for sprite rendering methods, refactor a bit, add some more overloads mainly for convenience --- .../gdx/graphics/DelayedSpriteBatch.java | 197 ++++++++++++++++-- src/com/blarg/gdx/graphics/RenderContext.java | 2 +- 2 files changed, 183 insertions(+), 16 deletions(-) diff --git a/src/com/blarg/gdx/graphics/DelayedSpriteBatch.java b/src/com/blarg/gdx/graphics/DelayedSpriteBatch.java index a979af2..133a2f0 100644 --- a/src/com/blarg/gdx/graphics/DelayedSpriteBatch.java +++ b/src/com/blarg/gdx/graphics/DelayedSpriteBatch.java @@ -1,11 +1,13 @@ package com.blarg.gdx.graphics; +import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; /*** @@ -24,12 +26,15 @@ import com.badlogic.gdx.utils.Array; *

*/ public class DelayedSpriteBatch { + static final Vector3 projTemp = new Vector3(); static final int CAPACITY_INCREMEMT = 128; Array sprites; int pointer; boolean hasBegun; SpriteBatch spriteBatch; + Camera perspectiveCamera; + int pixelScale; public DelayedSpriteBatch() { sprites = new Array(true, CAPACITY_INCREMEMT, Sprite.class); @@ -41,16 +46,24 @@ public class DelayedSpriteBatch { } public void begin(SpriteBatch spriteBatch) { + begin(spriteBatch, null, 1); + } + + public void begin(SpriteBatch spriteBatch, Camera perspectiveCamera, int pixelScale) { if (hasBegun) throw new IllegalStateException("Cannot be called within an existing begin/end block."); if (spriteBatch == null) throw new IllegalArgumentException(); this.spriteBatch = spriteBatch; + this.perspectiveCamera = perspectiveCamera; + this.pixelScale = pixelScale; hasBegun = true; pointer = 0; } + /**************************************************************************/ + public void draw(Texture texture, float x, float y) { draw(texture, x, y, texture.getWidth(), texture.getHeight(), Color.WHITE); } @@ -68,10 +81,33 @@ public class DelayedSpriteBatch { sprite.setTexture(texture); sprite.setRegion(0, 0, texture.getWidth(), texture.getHeight()); sprite.setColor(tint); - sprite.setSize(width, height); - sprite.setPosition(x, y); + sprite.setBounds(x, y, width, height); } + /**************************************************************************/ + + public void draw(Texture texture, float x, float y, float z) { + draw(texture, x, y, z, texture.getWidth(), texture.getHeight(), Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float z, Color tint) { + draw(texture, x, y, z, texture.getWidth(), texture.getHeight(), tint); + } + + public void draw(Texture texture, float x, float y, float z, float width, float height) { + draw(texture, x, y, z, width, height, Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float z, float width, float height, Color tint) { + Sprite sprite = nextUsable(); + sprite.setTexture(texture); + sprite.setRegion(0, 0, texture.getWidth(), texture.getHeight()); + sprite.setColor(tint); + setProjectedPositionAndSize(sprite, x, y, z, width, height); + } + + /**************************************************************************/ + public void draw(Texture texture, float x, float y, float width, float height, float u, float v, float u2, float v2) { draw(texture, x, y, width, height, u, v, u2, v2, Color.WHITE); } @@ -81,23 +117,69 @@ public class DelayedSpriteBatch { sprite.setTexture(texture); sprite.setRegion(u, v, u2, v2); sprite.setColor(tint); - sprite.setSize(width, height); - sprite.setPosition(x, y); + sprite.setBounds(x, y, width, height); } + /**************************************************************************/ + + public void draw(Texture texture, float x, float y, float z, float width, float height, float u, float v, float u2, float v2) { + draw(texture, x, y, z, width, height, u, v, u2, v2, Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float z, float width, float height, float u, float v, float u2, float v2, Color tint) { + Sprite sprite = nextUsable(); + sprite.setTexture(texture); + sprite.setRegion(u, v, u2, v2); + sprite.setColor(tint); + setProjectedPositionAndSize(sprite, x, y, z, width, height); + } + + /**************************************************************************/ + public void draw(Texture texture, float x, float y, int srcX, int srcY, int srcWidth, int srcHeight) { - draw(texture, x, y, srcX, srcY, srcWidth, srcHeight, Color.WHITE); + draw(texture, x, y, Math.abs(srcWidth), Math.abs(srcHeight), srcX, srcY, srcWidth, srcHeight, Color.WHITE); } public void draw(Texture texture, float x, float y, int srcX, int srcY, int srcWidth, int srcHeight, Color tint) { + draw(texture, x, y, Math.abs(srcWidth), Math.abs(srcHeight), srcX, srcY, srcWidth, srcHeight, tint); + } + + public void draw(Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth, int srcHeight) { + draw(texture, x, y, width, height, srcX, srcY, srcWidth, srcHeight, Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth, int srcHeight, Color tint) { Sprite sprite = nextUsable(); sprite.setTexture(texture); sprite.setRegion(srcX, srcY, srcWidth, srcHeight); sprite.setColor(tint); - sprite.setSize(Math.abs(srcWidth), Math.abs(srcHeight)); - sprite.setPosition(x, y); + sprite.setBounds(x, y, width, height); } + /**************************************************************************/ + + public void draw(Texture texture, float x, float y, float z, int srcX, int srcY, int srcWidth, int srcHeight) { + draw(texture, x, y, z, Math.abs(srcWidth), Math.abs(srcHeight), srcX, srcY, srcWidth, srcHeight, Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float z, int srcX, int srcY, int srcWidth, int srcHeight, Color tint) { + draw(texture, x, y, z, Math.abs(srcWidth), Math.abs(srcHeight), srcX, srcY, srcWidth, srcHeight, tint); + } + + public void draw(Texture texture, float x, float y, float z, float width, float height, int srcX, int srcY, int srcWidth, int srcHeight) { + draw(texture, x, y, z, width, height, srcX, srcY, srcWidth, srcHeight, Color.WHITE); + } + + public void draw(Texture texture, float x, float y, float z, float width, float height, int srcX, int srcY, int srcWidth, int srcHeight, Color tint) { + Sprite sprite = nextUsable(); + sprite.setTexture(texture); + sprite.setRegion(srcX, srcY, srcWidth, srcHeight); + sprite.setColor(tint); + setProjectedPositionAndSize(sprite, x, y, z, width, height); + } + + /**************************************************************************/ + public void draw(TextureRegion region, float x, float y) { draw(region, x, y, region.getRegionWidth(), region.getRegionWidth(), Color.WHITE); } @@ -114,20 +196,52 @@ public class DelayedSpriteBatch { Sprite sprite = nextUsable(); sprite.setRegion(region); sprite.setColor(tint); - sprite.setSize(width, height); - sprite.setPosition(x, y); + sprite.setBounds(x, y, width, height); } + /**************************************************************************/ + + public void draw(TextureRegion region, float x, float y, float z) { + draw(region, x, y, z, region.getRegionWidth(), region.getRegionWidth(), Color.WHITE); + } + + public void draw(TextureRegion region, float x, float y, float z, Color tint) { + draw(region, x, y, z, region.getRegionWidth(), region.getRegionWidth(), tint); + } + + public void draw(TextureRegion region, float x, float y, float z, float width, float height) { + draw(region, x, y, z, width, height, Color.WHITE); + } + + public void draw(TextureRegion region, float x, float y, float z, float width, float height, Color tint) { + Sprite sprite = nextUsable(); + sprite.setRegion(region); + sprite.setColor(tint); + setProjectedPositionAndSize(sprite, x, y, z, width, height); + } + + /**************************************************************************/ + public void draw(BitmapFont font, float x, float y, CharSequence str) { - draw(font, x, y, str, Color.WHITE); + draw(font, x, y, 1.0f, str, Color.WHITE); } public void draw(BitmapFont font, float x, float y, CharSequence str, Color tint) { + draw(font, x, y, 1.0f, str, tint); + } + + public void draw(BitmapFont font, float x, float y, float scale, CharSequence str) { + draw(font, x, y, scale, str, Color.WHITE); + } + + public void draw(BitmapFont font, float x, float y, float scale, CharSequence str, Color tint) { BitmapFont.BitmapFontData fontData = font.getData(); Texture fontTexture = font.getRegion().getTexture(); float currentX = x; float currentY = y; + float lineHeight = fontData.lineHeight * scale; + float spaceWidth = fontData.spaceWidth * scale; for (int i = 0; i < str.length(); ++i) { char c = str.charAt(i); @@ -136,7 +250,7 @@ public class DelayedSpriteBatch { if (c == '\r') continue; // can't render this anyway, and likely a '\n' is right behind ... if (c == '\n') { - currentY -= fontData.lineHeight; + currentY -= lineHeight; currentX = x; continue; } @@ -144,16 +258,46 @@ public class DelayedSpriteBatch { BitmapFont.Glyph glyph = fontData.getGlyph(c); if (glyph == null) { // TODO: maybe rendering some special char here instead would be better? - currentX += fontData.spaceWidth; + currentX += spaceWidth; continue; } - draw(fontTexture, currentX + glyph.xoffset, currentY + glyph.yoffset, glyph.srcX, glyph.srcY, glyph.width, glyph.height, tint); + float glyphWidth = ((float)glyph.width * scale); + float glyphHeight = ((float)glyph.height * scale); + draw( + fontTexture, + currentX + glyph.xoffset, currentY + glyph.yoffset, + glyphWidth, glyphHeight, + glyph.srcX, glyph.srcY, glyph.width, glyph.height, + tint + ); - currentX += glyph.xadvance; + currentX += ((float)glyph.xadvance * scale); } } + /**************************************************************************/ + + public void draw(BitmapFont font, float x, float y, float z, float scale, CharSequence str) { + draw(font, x, y, z, scale, str, Color.WHITE); + } + + public void draw(BitmapFont font, float x, float y, float z, float scale, CharSequence str, Color tint) { + BitmapFont.TextBounds bounds = font.getMultiLineBounds(str); + float scaledBoundsWidth = bounds.width * scale; + float scaledBoundsHeight = bounds.height * scale; + + getProjectedCenteredPosition(x, y, z, scaledBoundsWidth, scaledBoundsHeight, projTemp); + + // projected position is used as the position to center the whole text on + projTemp.x -= (scaledBoundsWidth / 2); + projTemp.y += (scaledBoundsHeight / 2); + + draw(font, projTemp.x, projTemp.y, scale, str, tint); + } + + /**************************************************************************/ + public void flush() { if (!hasBegun) throw new IllegalStateException("Cannot call outside of a begin/end block."); @@ -177,7 +321,30 @@ public class DelayedSpriteBatch { flush(); hasBegun = false; - spriteBatch = null; // don't need to hold on to this particular reference anymore + spriteBatch = null; // don't need to hold on to these references anymore + perspectiveCamera = null; + } + + private void getProjectedCenteredPosition(float x, float y, float z, float width, float height, Vector3 result) { + if (perspectiveCamera == null) + throw new UnsupportedOperationException("Cannot project 3D coordinates to screen space when no perspective camera is provided."); + + result.set(x, y, z); + perspectiveCamera.project(result); + + // screen coordinates will be unscaled, need to apply appropriate scaling... + result.x /= pixelScale; + result.y /= pixelScale; + } + + private void setProjectedPositionAndSize(Sprite sprite, float x, float y, float z, float width, float height) { + getProjectedCenteredPosition(x, y, z, width, height, projTemp); + + // projected position is used as the position to center the rendered sprite on + projTemp.x -= (width / 2); + projTemp.y -= (height / 2); + + sprite.setBounds(projTemp.x, projTemp.y, width, height); } private void increaseCapacity() { diff --git a/src/com/blarg/gdx/graphics/RenderContext.java b/src/com/blarg/gdx/graphics/RenderContext.java index 008d521..d6be3b4 100644 --- a/src/com/blarg/gdx/graphics/RenderContext.java +++ b/src/com/blarg/gdx/graphics/RenderContext.java @@ -84,7 +84,7 @@ public class RenderContext implements Disposable { public void onPreRender() { spriteBatch.setProjectionMatrix(orthographicCamera.combined); debugGeometryRenderer.begin(ShapeRenderer.ShapeType.Line); - delayedSpriteBatch.begin(spriteBatch); + delayedSpriteBatch.begin(spriteBatch, perspectiveCamera, pixelScaler.getScale()); billboardSpriteBatch.begin(decalBatch, perspectiveCamera); modelBatch.begin(perspectiveCamera); }