1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.graphics.g3d.utils.shapebuilders; 18 19 import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder; 20 import com.badlogic.gdx.math.Matrix4; 21 import com.badlogic.gdx.math.Vector3; 22 /** Helper class with static methods to build arrow shapes using {@link MeshPartBuilder}. 23 * @author xoppa */ 24 public class ArrowShapeBuilder extends BaseShapeBuilder { 25 /** Build an arrow 26 * @param x1 source x 27 * @param y1 source y 28 * @param z1 source z 29 * @param x2 destination x 30 * @param y2 destination y 31 * @param z2 destination z 32 * @param capLength is the height of the cap in percentage, must be in (0,1) 33 * @param stemThickness is the percentage of stem diameter compared to cap diameter, must be in (0,1] 34 * @param divisions the amount of vertices used to generate the cap and stem ellipsoidal bases */ build(MeshPartBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float capLength, float stemThickness, int divisions)35 public static void build (MeshPartBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float capLength, float stemThickness, 36 int divisions) { 37 Vector3 begin = obtainV3().set(x1, y1, z1), end = obtainV3().set(x2, y2, z2); 38 float length = begin.dst(end); 39 float coneHeight = length * capLength; 40 float coneDiameter = 2 * (float)(coneHeight * Math.sqrt(1f / 3)); 41 float stemLength = length - coneHeight; 42 float stemDiameter = coneDiameter * stemThickness; 43 44 Vector3 up = obtainV3().set(end).sub(begin).nor(); 45 Vector3 forward = obtainV3().set(up).crs(Vector3.Z); 46 if (forward.isZero()) forward.set(Vector3.X); 47 forward.crs(up).nor(); 48 Vector3 left = obtainV3().set(up).crs(forward).nor(); 49 Vector3 direction = obtainV3().set(end).sub(begin).nor(); 50 51 // Matrices 52 Matrix4 userTransform = builder.getVertexTransform(obtainM4()); 53 Matrix4 transform = obtainM4(); 54 float[] val = transform.val; 55 val[Matrix4.M00] = left.x; 56 val[Matrix4.M01] = up.x; 57 val[Matrix4.M02] = forward.x; 58 val[Matrix4.M10] = left.y; 59 val[Matrix4.M11] = up.y; 60 val[Matrix4.M12] = forward.y; 61 val[Matrix4.M20] = left.z; 62 val[Matrix4.M21] = up.z; 63 val[Matrix4.M22] = forward.z; 64 Matrix4 temp = obtainM4(); 65 66 // Stem 67 transform.setTranslation(obtainV3().set(direction).scl(stemLength / 2).add(x1, y1, z1)); 68 builder.setVertexTransform(temp.set(transform).mul(userTransform)); 69 CylinderShapeBuilder.build(builder, stemDiameter, stemLength, stemDiameter, divisions); 70 71 // Cap 72 transform.setTranslation(obtainV3().set(direction).scl(stemLength).add(x1, y1, z1)); 73 builder.setVertexTransform(temp.set(transform).mul(userTransform)); 74 ConeShapeBuilder.build(builder, coneDiameter, coneHeight, coneDiameter, divisions); 75 76 builder.setVertexTransform(userTransform); 77 freeAll(); 78 } 79 } 80