/*******************************************************************************
* Copyright 2015 See AUTHORS file.
*
* 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 com.mygdx.game.utilities;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.model.Node;
import com.badlogic.gdx.graphics.g3d.model.NodePart;
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import java.nio.FloatBuffer;
/**
* Created by user on 8/3/15.
*/
public class ModelFactory {
/**
* Translate each vertex along its normal by specified amount.
*
* @param model
* @param amount
*/
public static void fatten(Model model, float amount) {
Vector3 pos = new Vector3();
Vector3 nor = new Vector3();
for (Node node : model.nodes) {
for (NodePart n : node.parts) {
Mesh mesh = n.meshPart.mesh;
FloatBuffer buf = mesh.getVerticesBuffer();
int lastFloat = mesh.getNumVertices() * mesh.getVertexSize() / 4;
int vertexFloats = (mesh.getVertexSize() / 4);
VertexAttribute posAttr = mesh.getVertexAttributes().findByUsage(VertexAttributes.Usage.Position);
VertexAttribute norAttr = mesh.getVertexAttributes().findByUsage(VertexAttributes.Usage.Normal);
if (posAttr == null || norAttr == null) {
throw new IllegalArgumentException("Position/normal vertex attribute not found");
}
int pOff = posAttr.offset / 4;
int nOff = norAttr.offset / 4;
for (int i = 0; i < lastFloat; i += vertexFloats) {
pos.x = buf.get(pOff + i);
pos.y = buf.get(pOff + i + 1);
pos.z = buf.get(pOff + i + 2);
nor.x = buf.get(nOff + i);
nor.y = buf.get(nOff + i + 1);
nor.z = buf.get(nOff + i + 2);
nor.nor().scl(amount);
buf.put(pOff + i, pos.x + nor.x);
buf.put(pOff + i + 1, pos.y + nor.y);
buf.put(pOff + i + 2, pos.z + nor.z);
}
}
}
}
public static void createOutlineModel(Model model, Color outlineColor, float fattenAmount) {
fatten(model, fattenAmount);
for (Material m : model.materials) {
m.clear();
m.set(new IntAttribute(IntAttribute.CullFace, Gdx.gl.GL_FRONT));
m.set(ColorAttribute.createDiffuse(outlineColor));
}
}
public static Model buildPlaneModel(final float width,
final float height, final Material material, final float u1,
final float v1, final float u2, final float v2) {
ModelBuilder modelBuilder = new ModelBuilder();
modelBuilder.begin();
MeshPartBuilder bPartBuilder = modelBuilder.part("rect", GL20.GL_TRIANGLES,
VertexAttributes.Usage.Position
| VertexAttributes.Usage.Normal
| VertexAttributes.Usage.TextureCoordinates, material);
bPartBuilder.setUVRange(u1, v1, u2, v2);
bPartBuilder.rect(-(width * 0.5f), -(height * 0.5f), 0, (width * 0.5f),
-(height * 0.5f), 0, (width * 0.5f), (height * 0.5f), 0,
-(width * 0.5f), (height * 0.5f), 0, 0, 0, -1);
return (modelBuilder.end());
}
public static Model buildBillboardModel(Texture texture, float width, float height) {
TextureRegion textureRegion = new TextureRegion(texture, texture.getWidth(), texture.getHeight());
Material material = new Material();
material.set(new TextureAttribute(TextureAttribute.Diffuse, textureRegion));
material.set(new ColorAttribute(ColorAttribute.AmbientLight, Color.WHITE));
material.set(new BlendingAttribute());
return ModelFactory.buildPlaneModel(width, height, material, 0, 0, 1, 1);
}
public static Model buildCompassModel() {
float compassScale = 5;
ModelBuilder modelBuilder = new ModelBuilder();
Model arrow = modelBuilder.createArrow(Vector3.Zero,
Vector3.Y.cpy().scl(compassScale), null,
VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal);
modelBuilder.begin();
Mesh zArrow = arrow.meshes.first().copy(false);
zArrow.transform(new Matrix4().rotate(Vector3.X, 90));
modelBuilder.part("part1", zArrow, GL20.GL_TRIANGLES,
new Material(ColorAttribute.createDiffuse(Color.BLUE)));
modelBuilder.node();
Mesh yArrow = arrow.meshes.first().copy(false);
modelBuilder.part("part2", yArrow, GL20.GL_TRIANGLES,
new Material(ColorAttribute.createDiffuse(Color.GREEN)));
modelBuilder.node();
Mesh xArrow = arrow.meshes.first().copy(false);
xArrow.transform(new Matrix4().rotate(Vector3.Z, -90));
modelBuilder.part("part3", xArrow, GL20.GL_TRIANGLES,
new Material(ColorAttribute.createDiffuse(Color.RED)));
arrow.dispose();
return modelBuilder.end();
}
}