package org.osm2world.core.world.modules.common;
import static java.util.Arrays.asList;
import static java.util.Collections.nCopies;
import java.util.List;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;
import org.osm2world.core.target.Target;
import org.osm2world.core.target.common.material.Material;
/**
* utility class for drawing billboards, particularly "cross tree" shapes
*/
public final class WorldModuleBillboardUtil {
private WorldModuleBillboardUtil() { }
/**
* renders a "cross tree" shape.
*
* This shape is composed from two rectangular billboards, each with front
* and back side, intersecting orthogonally. Each billboard consists of
* two halves, separated at the billboard's intersection axis,
* to allow sorting of primitives for transparent rendering.
*/
public static final void renderCrosstree(Target<?> target,
Material material, VectorXYZ pos,
double width, double height,
boolean mirroredTextures) {
double halfWidth = 0.5 * width;
VectorXYZ xPosBottom = pos.add(halfWidth, 0, 0);
VectorXYZ xNegBottom = pos.add(-halfWidth, 0, 0);
VectorXYZ zPosBottom = pos.add(0, 0, halfWidth);
VectorXYZ zNegBottom = pos.add(0, 0, -halfWidth);
VectorXYZ xPosTop = xPosBottom.add(0, height, 0);
VectorXYZ xNegTop = xNegBottom.add(0, height, 0);
VectorXYZ zPosTop = zPosBottom.add(0, height, 0);
VectorXYZ zNegTop = zNegBottom.add(0, height, 0);
VectorXYZ posTop = pos.add(0, height, 0);
target.drawTriangleStrip(material, asList(
xNegTop, xNegBottom, posTop, pos),
buildBillboardTexCoordLists(false, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
xPosBottom, xPosTop, pos, posTop),
buildBillboardTexCoordLists(true, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
zNegTop, zNegBottom, posTop, pos),
buildBillboardTexCoordLists(false, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
zPosBottom, zPosTop, pos, posTop),
buildBillboardTexCoordLists(true, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
xPosTop, xPosBottom, posTop, pos),
buildBillboardTexCoordLists(false, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
xNegBottom, xNegTop, pos, posTop),
buildBillboardTexCoordLists(true, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
zPosTop, zPosBottom, posTop, pos),
buildBillboardTexCoordLists(false, mirroredTextures,
material.getTextureDataList().size()));
target.drawTriangleStrip(material, asList(
zNegBottom, zNegTop, pos, posTop),
buildBillboardTexCoordLists(true, mirroredTextures,
material.getTextureDataList().size()));
}
private static final List<List<VectorXZ>> buildBillboardTexCoordLists(
boolean right, boolean mirrored, int copies) {
if (right) {
if (mirrored) {
if (copies <= 3) { return BILLBOARD_RIGHT_TEX_COORDS_MIRRORED_COPIES[copies]; }
else { return nCopies(copies, BILLBOARD_RIGHT_TEX_COORDS_MIRRORED); }
} else {
if (copies <= 3) { return BILLBOARD_RIGHT_TEX_COORDS_COPIES[copies]; }
else { return nCopies(copies, BILLBOARD_RIGHT_TEX_COORDS); }
}
} else {
if (mirrored) {
if (copies <= 3) { return BILLBOARD_LEFT_TEX_COORDS_MIRRORED_COPIES[copies]; }
else { return nCopies(copies, BILLBOARD_LEFT_TEX_COORDS_MIRRORED); }
} else {
if (copies <= 3) { return BILLBOARD_LEFT_TEX_COORDS_COPIES[copies]; }
else { return nCopies(copies, BILLBOARD_LEFT_TEX_COORDS); }
}
}
}
private static final List<VectorXZ> BILLBOARD_LEFT_TEX_COORDS = asList(
VectorXZ.Z_UNIT, VectorXZ.NULL_VECTOR,
new VectorXZ(0.5, 1), new VectorXZ(0.5, 0));
private static final List<VectorXZ> BILLBOARD_LEFT_TEX_COORDS_MIRRORED = asList(
new VectorXZ(1, 1), VectorXZ.X_UNIT,
new VectorXZ(0.5, 1), new VectorXZ(0.5, 0));
private static final List<VectorXZ> BILLBOARD_RIGHT_TEX_COORDS = asList(
VectorXZ.X_UNIT, new VectorXZ(1, 1),
new VectorXZ(0.5, 0), new VectorXZ(0.5, 1));
private static final List<VectorXZ> BILLBOARD_RIGHT_TEX_COORDS_MIRRORED = asList(
VectorXZ.NULL_VECTOR, VectorXZ.Z_UNIT,
new VectorXZ(0.5, 0), new VectorXZ(0.5, 1));
@SuppressWarnings("unchecked")
private static final List<List<VectorXZ>>[] BILLBOARD_LEFT_TEX_COORDS_COPIES = new List[]{
nCopies(0, BILLBOARD_LEFT_TEX_COORDS),
nCopies(1, BILLBOARD_LEFT_TEX_COORDS),
nCopies(2, BILLBOARD_LEFT_TEX_COORDS),
nCopies(3, BILLBOARD_LEFT_TEX_COORDS)
};
@SuppressWarnings("unchecked")
private static final List<List<VectorXZ>>[] BILLBOARD_LEFT_TEX_COORDS_MIRRORED_COPIES = new List[]{
nCopies(0, BILLBOARD_LEFT_TEX_COORDS_MIRRORED),
nCopies(1, BILLBOARD_LEFT_TEX_COORDS_MIRRORED),
nCopies(2, BILLBOARD_LEFT_TEX_COORDS_MIRRORED),
nCopies(3, BILLBOARD_LEFT_TEX_COORDS_MIRRORED)
};
@SuppressWarnings("unchecked")
private static final List<List<VectorXZ>>[] BILLBOARD_RIGHT_TEX_COORDS_COPIES = new List[]{
nCopies(0, BILLBOARD_RIGHT_TEX_COORDS),
nCopies(1, BILLBOARD_RIGHT_TEX_COORDS),
nCopies(2, BILLBOARD_RIGHT_TEX_COORDS),
nCopies(3, BILLBOARD_RIGHT_TEX_COORDS)
};
@SuppressWarnings("unchecked")
private static final List<List<VectorXZ>>[] BILLBOARD_RIGHT_TEX_COORDS_MIRRORED_COPIES = new List[]{
nCopies(0, BILLBOARD_RIGHT_TEX_COORDS_MIRRORED),
nCopies(1, BILLBOARD_RIGHT_TEX_COORDS_MIRRORED),
nCopies(2, BILLBOARD_RIGHT_TEX_COORDS_MIRRORED),
nCopies(3, BILLBOARD_RIGHT_TEX_COORDS_MIRRORED)
};
}