/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.iconmesh;
import org.terasology.utilities.Assets;
import org.terasology.assets.Asset;
import org.terasology.assets.ResourceUrn;
import org.terasology.math.geom.Rect2i;
import org.terasology.math.geom.Vector4f;
import org.terasology.module.sandbox.API;
import org.terasology.naming.Name;
import org.terasology.rendering.assets.mesh.Mesh;
import org.terasology.rendering.assets.mesh.MeshData;
import org.terasology.rendering.assets.texture.TextureRegion;
import org.terasology.rendering.primitives.Tessellator;
import org.terasology.rendering.primitives.TessellatorHelper;
import java.nio.ByteBuffer;
@API
public final class IconMeshFactory {
private IconMeshFactory() {
}
public static Mesh getIconMesh(TextureRegion region) {
if (region instanceof Asset) {
ResourceUrn urn = ((Asset<?>) region).getUrn();
if (urn.getFragmentName().isEmpty()) {
return Assets.get(new ResourceUrn(urn.getModuleName(), IconMeshDataProducer.ICON_DISCRIMINATOR, urn.getResourceName()), Mesh.class).get();
} else {
Name fragName = new Name(urn.getResourceName().toString() + ResourceUrn.FRAGMENT_SEPARATOR + urn.getFragmentName().toString());
return Assets.get(new ResourceUrn(urn.getModuleName(), IconMeshDataProducer.ICON_DISCRIMINATOR, fragName), Mesh.class).get();
}
} else {
return generateIconMesh(region);
}
}
public static Mesh generateIconMesh(TextureRegion tex) {
return generateIconMesh(null, tex, 0, false, null);
}
public static Mesh generateIconMesh(ResourceUrn urn, TextureRegion tex) {
return generateIconMesh(urn, tex, 0, false, null);
}
public static MeshData generateIconMeshData(TextureRegion tex) {
return generateIconMeshData(tex, 0, false, null);
}
public static Mesh generateIconMesh(ResourceUrn urn, TextureRegion tex, int alphaLimit, boolean withContour, Vector4f colorContour) {
if (urn == null) {
return Assets.generateAsset(generateIconMeshData(tex, alphaLimit, withContour, colorContour), Mesh.class);
} else {
return Assets.generateAsset(urn, generateIconMeshData(tex, alphaLimit, withContour, colorContour), Mesh.class);
}
}
public static MeshData generateIconMeshData(TextureRegion tex, int alphaLimit, boolean withContour, Vector4f colorContour) {
ByteBuffer buffer = tex.getTexture().getData().getBuffers()[0];
Rect2i pixelRegion = tex.getPixelRegion();
int posX = pixelRegion.minX();
int posY = pixelRegion.minY();
int stride = tex.getTexture().getWidth() * 4;
float textureSize = Math.max(tex.getWidth(), tex.getHeight());
Tessellator tessellator = new Tessellator();
for (int y = 0; y < tex.getHeight(); y++) {
for (int x = 0; x < tex.getWidth(); x++) {
int r = buffer.get((posY + y) * stride + (posX + x) * 4) & 255;
int g = buffer.get((posY + y) * stride + (posX + x) * 4 + 1) & 255;
int b = buffer.get((posY + y) * stride + (posX + x) * 4 + 2) & 255;
int a = buffer.get((posY + y) * stride + (posX + x) * 4 + 3) & 255;
if (a > alphaLimit) {
Vector4f color = new Vector4f(r / 255f, g / 255f, b / 255f, a / 255f);
TessellatorHelper.addBlockMesh(tessellator, color, 2f / textureSize, 1.0f, 0.5f,
2f / textureSize * x - 1f, 2f / textureSize * (tex.getHeight() - y - 1) - 1f, 0f);
if (withContour) {
int newX = 0;
int newY = 0;
int newA = 0;
for (int i = 0; i < 4; i++) {
newA = alphaLimit + 1;
switch (i) {
case 0:
//check left
if (x > 0) {
newX = x - 1;
newY = y;
newA = buffer.get((posY + newY) * stride + (posX + newX) * 4 + 3) & 255;
}
break;
case 1:
//check top
if (y > 0) {
newX = x;
newY = y - 1;
newA = buffer.get((posY + newY) * stride + (posX + newX) * 4 + 3) & 255;
}
break;
case 2:
//check right
if (x < 16) {
newX = x + 1;
newY = y;
newA = buffer.get((posY + newY) * stride + (posX + newX) * 4 + 3) & 255;
}
break;
case 3:
//check bottom
if (y < 16) {
newX = x;
newY = y + 1;
newA = buffer.get((posY + newY) * stride + (posX + newX) * 4 + 3) & 255;
}
break;
default:
break;
}
if (newA < alphaLimit) {
Vector4f cColor = new Vector4f(colorContour.x / 255f, colorContour.y / 255f, colorContour.z / 255f, colorContour.w);
TessellatorHelper.addBlockMesh(tessellator, cColor, 0.125f, 1.0f, 0.5f, 2f * 0.0625f * newX - 0.5f, 0.125f * (15 - newY) - 1f, 0f);
}
}
}
}
}
}
return tessellator.generateMeshData();
}
}