ca.blarg.gdx.tilemap3d.tilemesh.MultiModelTileMesh Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gdx-tilemap3d Show documentation
Show all versions of gdx-tilemap3d Show documentation
Library to handle management and rendering of a game world composed of 3D "tiles" arranged in a uniform 3D grid, via libGDX.
The newest version!
package ca.blarg.gdx.tilemap3d.tilemesh;
import ca.blarg.gdx.graphics.Vertices;
import ca.blarg.gdx.graphics.atlas.MaterialTileMapping;
import ca.blarg.gdx.math.MathHelpers;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.Array;
public class MultiModelTileMesh extends BaseModelTileMesh {
BoundingBox bounds;
Vertices vertices;
Array collisionVertices;
Vector3 scaleToSize;
Vector3 positionOffset;
Vector3 collisionPositionOffset;
@Override
public BoundingBox getBounds() {
return bounds;
}
@Override
public Vertices getVertices() {
return vertices;
}
@Override
public Vector3[] getCollisionVertices() {
return collisionVertices.items;
}
public MultiModelTileMesh(
Model[] models,
Color[] modelColors,
Vector3[] scaleModelsToSizes,
Vector3[] modelPositionOffsets,
Model collisionModel,
MaterialTileMapping textures,
byte opaqueSides,
byte lightValue,
boolean alpha,
float translucency,
Color color,
Vector3 scaleToSize,
Vector3 positionOffset,
Vector3 collisionPositionOffset
) {
super(opaqueSides, alpha, translucency, lightValue, color);
if (modelColors.length != models.length || scaleModelsToSizes.length != models.length || modelPositionOffsets.length != models.length)
throw new RuntimeException("Mismatching number of submodel data provided.");
initScalingAndOffsetParams(scaleToSize, positionOffset, collisionPositionOffset);
setupMesh(models, modelColors, scaleModelsToSizes, modelPositionOffsets, textures);
setupCollisionVertices(collisionModel);
}
private void initScalingAndOffsetParams(Vector3 scaleToSize, Vector3 positionOffset, Vector3 collisionPositionOffset) {
this.scaleToSize = (scaleToSize == null ? null : new Vector3(scaleToSize));
this.positionOffset = (positionOffset == null ? new Vector3(Vector3.Zero) : new Vector3(positionOffset));
this.collisionPositionOffset = (collisionPositionOffset == null ? new Vector3(Vector3.Zero) : new Vector3(collisionPositionOffset));
}
private void setupMesh(
Model[] models,
Color[] modelColors,
Vector3[] scaleModelsToSizes,
Vector3[] modelPositionOffsets,
MaterialTileMapping textures
) {
// setup vertices collection size to the proper amount to hold all submodel vertices
int numVertices = 0;
for (int i = 0; i < models.length; ++i)
numVertices += countModelVertices(models[i]);
vertices = new Vertices(
numVertices,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.Normal(),
VertexAttribute.TexCoords(0)
);
bounds = new BoundingBox();
BoundingBox tmpBounds = new BoundingBox();
// collect the vertices from each of the models provided
for (int i = 0; i < models.length; ++i) {
Model submodel = models[i];
Color color = modelColors[i];
Vector3 scaleToSize = scaleModelsToSizes[i];
Vector3 positionOffset = modelPositionOffsets[i];
if (positionOffset == null)
positionOffset = Vector3.Zero;
// find the bounds of this submodel (scaled if necessary) and extend the final tilemesh
// bounds as needed by this submodel's bounds.
// also find the scale factor to scale the model to the requested size at the same time
BoundingBox submodelBounds = new BoundingBox();
Vector3 scaleFactor = new Vector3();
submodel.calculateBoundingBox(tmpBounds);
if (scaleToSize != null) {
MathHelpers.getScaleFactor(tmpBounds.getDimensions(), scaleToSize, scaleFactor);
submodelBounds.set(Vector3.Zero, scaleToSize);
} else {
submodelBounds.set(Vector3.Zero, tmpBounds.getDimensions());
scaleFactor.set(1.0f, 1.0f, 1.0f);
}
bounds.ext(submodelBounds);
for (int j = 0; j < submodel.nodes.size; ++j)
collectModelNodeVertices(submodel.nodes.get(j), vertices, textures, color, scaleFactor, positionOffset);
}
// final scaling and offsets by the overall model scale/offsets (if provided)
// figure out what the final scaled bounds and scale factor will be
Vector3 scaleFactor = new Vector3();
if (scaleToSize != null) {
MathHelpers.getScaleFactor(bounds.getDimensions(), scaleToSize, scaleFactor);
bounds = new BoundingBox().set(Vector3.Zero, scaleToSize);
} else {
bounds = new BoundingBox().set(Vector3.Zero, bounds.getDimensions());
scaleFactor.set(1.0f, 1.0f, 1.0f);
}
// now apply the scale factor and offset to each vertex
Vector3 position = new Vector3();
for (int i = 0; i < vertices.count(); ++i) {
vertices.getPos(i, position);
position.add(positionOffset)
.scl(scaleFactor);
vertices.setPos(i, position);
}
}
private void setupCollisionVertices(Model collisionModel) {
if (collisionModel != null) {
BoundingBox tmpBounds = new BoundingBox();
Vector3 scaleFactor = new Vector3();
if (scaleToSize != null) {
collisionModel.calculateBoundingBox(tmpBounds);
MathHelpers.getScaleFactor(tmpBounds.getDimensions(), scaleToSize, scaleFactor);
} else
scaleFactor.set(1.0f, 1.0f, 1.0f);
int numVertices = countModelVertices(collisionModel);
collisionVertices = new Array(true, numVertices, Vector3.class);
for (int i = 0; i < collisionModel.nodes.size; ++i)
collectModelNodeVertexPositions(collisionModel.nodes.get(i), collisionVertices, scaleFactor, collisionPositionOffset);
} else {
// if no collision model is provided, just use the mesh vertices we (should have) previously collected
// from all the submodels. they will already be scaled/offset appropriately so this is just a simple copy
collisionVertices = new Array(true, vertices.count(), Vector3.class);
for (int i = 0; i < vertices.count(); ++i) {
Vector3 v = new Vector3();
vertices.getPos(i, v);
collisionVertices.add(v);
}
}
}
@Override
public void dispose() {
}
}