/******************************************************************************* * Copyright 2011 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.badlogic.gdx.graphics.g3d.utils.shapebuilders; import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector3; /** Helper class with static methods to build arrow shapes using {@link MeshPartBuilder}. * @author xoppa */ public class ArrowShapeBuilder extends BaseShapeBuilder { /** Build an arrow * @param x1 source x * @param y1 source y * @param z1 source z * @param x2 destination x * @param y2 destination y * @param z2 destination z * @param capLength is the height of the cap in percentage, must be in (0,1) * @param stemThickness is the percentage of stem diameter compared to cap diameter, must be in (0,1] * @param divisions the amount of vertices used to generate the cap and stem ellipsoidal bases */ public static void build (MeshPartBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float capLength, float stemThickness, int divisions) { Vector3 begin = obtainV3().set(x1, y1, z1), end = obtainV3().set(x2, y2, z2); float length = begin.dst(end); float coneHeight = length * capLength; float coneDiameter = 2 * (float)(coneHeight * Math.sqrt(1f / 3)); float stemLength = length - coneHeight; float stemDiameter = coneDiameter * stemThickness; Vector3 up = obtainV3().set(end).sub(begin).nor(); Vector3 forward = obtainV3().set(up).crs(Vector3.Z); if (forward.isZero()) forward.set(Vector3.X); forward.crs(up).nor(); Vector3 left = obtainV3().set(up).crs(forward).nor(); Vector3 direction = obtainV3().set(end).sub(begin).nor(); // Matrices Matrix4 userTransform = builder.getVertexTransform(obtainM4()); Matrix4 transform = obtainM4(); float[] val = transform.val; val[Matrix4.M00] = left.x; val[Matrix4.M01] = up.x; val[Matrix4.M02] = forward.x; val[Matrix4.M10] = left.y; val[Matrix4.M11] = up.y; val[Matrix4.M12] = forward.y; val[Matrix4.M20] = left.z; val[Matrix4.M21] = up.z; val[Matrix4.M22] = forward.z; Matrix4 temp = obtainM4(); // Stem transform.setTranslation(obtainV3().set(direction).scl(stemLength / 2).add(x1, y1, z1)); builder.setVertexTransform(temp.set(transform).mul(userTransform)); CylinderShapeBuilder.build(builder, stemDiameter, stemLength, stemDiameter, divisions); // Cap transform.setTranslation(obtainV3().set(direction).scl(stemLength).add(x1, y1, z1)); builder.setVertexTransform(temp.set(transform).mul(userTransform)); ConeShapeBuilder.build(builder, coneDiameter, coneHeight, coneDiameter, divisions); builder.setVertexTransform(userTransform); freeAll(); } }