/* * The MIT License * * Copyright (c) 2015-2021 Kai Burjack * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jozufozu.flywheel.repack.joml; /** * Useful geometry methods. * * @author Kai Burjack * @author Richard Greenlees */ public class GeometryUtils { /** * Compute two arbitrary vectors perpendicular to the given normalized vector (x, y, z), and store them in dest1 and dest2, * respectively. *

* The computed vectors will themselves be perpendicular to each another and normalized. So the tree vectors (x, y, z), dest1 and * dest2 form an orthonormal basis. * * @param x * the x coordinate of the normalized input vector * @param y * the y coordinate of the normalized input vector * @param z * the z coordinate of the normalized input vector * @param dest1 * will hold the first perpendicular vector * @param dest2 * will hold the second perpendicular vector */ public static void perpendicular(float x, float y, float z, Vector3f dest1, Vector3f dest2) { float magX = z * z + y * y; float magY = z * z + x * x; float magZ = y * y + x * x; float mag; if (magX > magY && magX > magZ) { dest1.x = 0; dest1.y = z; dest1.z = -y; mag = magX; } else if (magY > magZ) { dest1.x = -z; dest1.y = 0; dest1.z = x; mag = magY; } else { dest1.x = y; dest1.y = -x; dest1.z = 0; mag = magZ; } float len = Math.invsqrt(mag); dest1.x *= len; dest1.y *= len; dest1.z *= len; dest2.x = y * dest1.z - z * dest1.y; dest2.y = z * dest1.x - x * dest1.z; dest2.z = x * dest1.y - y * dest1.x; } /** * Compute two arbitrary vectors perpendicular to the given normalized vector v, and store them in dest1 and dest2, * respectively. *

* The computed vectors will themselves be perpendicular to each another and normalized. So the tree vectors v, dest1 and * dest2 form an orthonormal basis. * * @param v * the {@link Vector3f#normalize() normalized} input vector * @param dest1 * will hold the first perpendicular vector * @param dest2 * will hold the second perpendicular vector */ public static void perpendicular(Vector3fc v, Vector3f dest1, Vector3f dest2) { perpendicular(v.x(), v.y(), v.z(), dest1, dest2); } /** * Calculate the normal of a surface defined by points v1, v2 and v3 and store it in dest. * * @param v0 * the first position * @param v1 * the second position * @param v2 * the third position * @param dest * will hold the result */ public static void normal(Vector3fc v0, Vector3fc v1, Vector3fc v2, Vector3f dest) { normal(v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), dest); } /** * Calculate the normal of a surface defined by points (v1X, v1Y, v1Z), (v2X, v2Y, v2Z) and (v3X, v3Y, v3Z) * and store it in dest. * * @param v0X * the x coordinate of the first position * @param v0Y * the y coordinate of the first position * @param v0Z * the z coordinate of the first position * @param v1X * the x coordinate of the second position * @param v1Y * the y coordinate of the second position * @param v1Z * the z coordinate of the second position * @param v2X * the x coordinate of the third position * @param v2Y * the y coordinate of the third position * @param v2Z * the z coordinate of the third position * @param dest * will hold the result */ public static void normal(float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, Vector3f dest) { dest.x = ((v1Y - v0Y) * (v2Z - v0Z)) - ((v1Z - v0Z) * (v2Y - v0Y)); dest.y = ((v1Z - v0Z) * (v2X - v0X)) - ((v1X - v0X) * (v2Z - v0Z)); dest.z = ((v1X - v0X) * (v2Y - v0Y)) - ((v1Y - v0Y) * (v2X - v0X)); dest.normalize(); } /** * Calculate the surface tangent for the three supplied vertices and UV coordinates and store the result in dest. * * @param v1 * XYZ of first vertex * @param uv1 * UV of first vertex * @param v2 * XYZ of second vertex * @param uv2 * UV of second vertex * @param v3 * XYZ of third vertex * @param uv3 * UV of third vertex * @param dest * the tangent will be stored here */ public static void tangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f dest) { float DeltaV1 = uv2.y() - uv1.y(); float DeltaV2 = uv3.y() - uv1.y(); float f = 1.0f / ((uv2.x() - uv1.x()) * DeltaV2 - (uv3.x() - uv1.x()) * DeltaV1); dest.x = f * (DeltaV2 * (v2.x() - v1.x()) - DeltaV1 * (v3.x() - v1.x())); dest.y = f * (DeltaV2 * (v2.y() - v1.y()) - DeltaV1 * (v3.y() - v1.y())); dest.z = f * (DeltaV2 * (v2.z() - v1.z()) - DeltaV1 * (v3.z() - v1.z())); dest.normalize(); } /** * Calculate the surface bitangent for the three supplied vertices and UV coordinates and store the result in dest. * * @param v1 * XYZ of first vertex * @param uv1 * UV of first vertex * @param v2 * XYZ of second vertex * @param uv2 * UV of second vertex * @param v3 * XYZ of third vertex * @param uv3 * UV of third vertex * @param dest * the binormal will be stored here */ public static void bitangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f dest) { float DeltaU1 = uv2.x() - uv1.x(); float DeltaU2 = uv3.x() - uv1.x(); float f = 1.0f / (DeltaU1 * (uv3.y() - uv1.y()) - DeltaU2 * (uv2.y() - uv1.y())); dest.x = f * (-DeltaU2 * (v2.x() - v1.x()) + DeltaU1 * (v3.x() - v1.x())); dest.y = f * (-DeltaU2 * (v2.y() - v1.y()) + DeltaU1 * (v3.y() - v1.y())); dest.z = f * (-DeltaU2 * (v2.z() - v1.z()) + DeltaU1 * (v3.z() - v1.z())); dest.normalize(); } /** * Calculate the surface tangent and bitangent for the three supplied vertices and UV coordinates and store the result in dest. * * @param v1 * XYZ of first vertex * @param uv1 * UV of first vertex * @param v2 * XYZ of second vertex * @param uv2 * UV of second vertex * @param v3 * XYZ of third vertex * @param uv3 * UV of third vertex * @param destTangent * the tangent will be stored here * @param destBitangent * the bitangent will be stored here */ public static void tangentBitangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f destTangent, Vector3f destBitangent) { float DeltaV1 = uv2.y() - uv1.y(); float DeltaV2 = uv3.y() - uv1.y(); float DeltaU1 = uv2.x() - uv1.x(); float DeltaU2 = uv3.x() - uv1.x(); float f = 1.0f / (DeltaU1 * DeltaV2 - DeltaU2 * DeltaV1); destTangent.x = f * (DeltaV2 * (v2.x() - v1.x()) - DeltaV1 * (v3.x() - v1.x())); destTangent.y = f * (DeltaV2 * (v2.y() - v1.y()) - DeltaV1 * (v3.y() - v1.y())); destTangent.z = f * (DeltaV2 * (v2.z() - v1.z()) - DeltaV1 * (v3.z() - v1.z())); destTangent.normalize(); destBitangent.x = f * (-DeltaU2 * (v2.x() - v1.x()) + DeltaU1 * (v3.x() - v1.x())); destBitangent.y = f * (-DeltaU2 * (v2.y() - v1.y()) + DeltaU1 * (v3.y() - v1.y())); destBitangent.z = f * (-DeltaU2 * (v2.z() - v1.z()) + DeltaU1 * (v3.z() - v1.z())); destBitangent.normalize(); } }