All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.j3d.util.TriangleUtils Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/*****************************************************************************
 *                        J3D.org Copyright (c) 2000
 *                               Java Source
 *
 * This source is licensed under the GNU LGPL v2.1
 * Please read http://www.gnu.org/copyleft/lgpl.html for more information
 *
 ****************************************************************************/

package org.j3d.util;

// External imports
// None

// Local imports
// None

/**
 * An set of utility functions for taking basic triangle information and
 * returning derived information that is useful for rendering.
 * 

* * The tangent generation code is derived from Eric Lengyel's * Computing Tangent Space Basis Vectors for an Arbitrary Mesh * * http://www.terathon.com/code/tangent.html *

* * Internationalisation Resource Names *

*

    *
  • nullTexCoordMsg: The tangent array parameter was null
  • *
  • nullNormalsMsg: The tangent array parameter was null
  • *
  • nullCoordsMsg: The tangent array parameter was null
  • *
  • nullIndexMsg: The tangent array parameter was null
  • *
  • nullTangentMsg: The tangent array parameter was null
  • *
* * @author Justin Couch * @version $Revision: 1.3 $ */ public class TriangleUtils { /** The message string the user didn't provide texture coordinates */ private static final String MISSING_TEXCOORD_PROP = "org.j3d.util.interpolator.TriangleUtils.nullTexCoordMsg"; /** The message string the user didn't provide normals */ private static final String MISSING_NORMALS_PROP = "org.j3d.util.interpolator.TriangleUtils.nullNormalsMsg"; /** The message string the user didn't provide coordinates */ private static final String MISSING_COORDS_PROP = "org.j3d.util.interpolator.TriangleUtils.nullCoordsMsg"; /** The message string the user didn't provide coord indices */ private static final String MISSING_INDEX_PROP = "org.j3d.util.interpolator.TriangleUtils.nullIndexMsg"; /** The message string the user didn't provide tangent */ private static final String MISSING_TANGENT_PROP = "org.j3d.util.interpolator.TriangleUtils.nullTangentMsg"; /** * Generate tangent space vectors and Binormals (Bitangents). Assumes * that per-vertex normals are provided and it is index triangles. * * @param numTriangles The number of triangles to process from the * index list - assuming indexed triangles and nothing more fancy * like strips or fans * @param indices The list of vertex indices where each i is the * index, not multiplying in the 3x for flattened coords * @param coords The list of coordinates to process as a flat list * @param normals The list of normals, one per vertex, flattened * @param texCoords The list of 2D texture coordinates, one per * vertex, flattened * @param tangents The array to put the returned tangents in, must * be 4x the number of coordinates as it is provided in x,y,z,angle * form * @throws NullPointerException One of the arrays provided was * null. Message contains the details of which one */ public static void createTangents(int numTriangles, int[] indices, float[] coords, float[] normals, float[] texCoords, float[] tangents) { if(indices == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_INDEX_PROP); throw new NullPointerException(msg); } if(coords == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_COORDS_PROP); throw new NullPointerException(msg); } if(normals == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_NORMALS_PROP); throw new NullPointerException(msg); } if(texCoords == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_TEXCOORD_PROP); throw new NullPointerException(msg); } if(tangents == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_TANGENT_PROP); throw new NullPointerException(msg); } // Find the max index: int max_index = 0; for(int i = 0; i < numTriangles * 3; i++) { if(indices[i] > max_index) max_index = indices[i]; } max_index++; float[] tan1 = new float[max_index * 3]; float[] tan2 = new float[max_index * 3]; for(int i = 0; i < numTriangles; i++) { float x1 = coords[indices[i * 3 + 1] * 3] - coords[indices[i * 3] * 3]; float x2 = coords[indices[i * 3 + 2] * 3] - coords[indices[i * 3] * 3]; float y1 = coords[indices[i * 3 + 1] * 3 + 1] - coords[indices[i * 3] * 3 + 1]; float y2 = coords[indices[i * 3 + 2] * 3 + 1] - coords[indices[i * 3] * 3 + 1]; float z1 = coords[indices[i * 3 + 1] * 3 + 2] - coords[indices[i * 3] * 3 + 2]; float z2 = coords[indices[i * 3 + 2] * 3 + 2] - coords[indices[i * 3] * 3 + 2]; float s1 = texCoords[indices[i * 3 + 1] * 2] - texCoords[indices[i * 3] * 2]; float s2 = texCoords[indices[i * 3 + 2] * 2] - texCoords[indices[i * 3] * 2]; float t1 = texCoords[indices[i * 3 + 1] * 2 + 1] - texCoords[indices[i * 3] * 2 + 1]; float t2 = texCoords[indices[i * 3 + 2] * 2 + 1] - texCoords[indices[i * 3] * 2 + 1]; float r = 1.0f / (s1 * t2 - s2 * t1); float sdir_x = (t2 * x1 - t1 * x2) * r; float sdir_y = (t2 * y1 - t1 * y2) * r; float sdir_z = (t2 * z1 - t1 * z2) * r; float tdir_x = (s1 * x2 - s2 * x1) * r; float tdir_y = (s1 * y2 - s2 * y1) * r; float tdir_z = (s1 * z2 - s2 * z1) * r; for (int j = 0; j < 3; j++) { tan1[indices[i * 3 + j] * 3] += sdir_x; tan1[indices[i * 3 + j] * 3 + 1] += sdir_y; tan1[indices[i * 3 + j] * 3 + 2] += sdir_z; tan2[indices[i * 3 + j] * 3] += tdir_x; tan2[indices[i * 3 + j] * 3 + 1] += tdir_y; tan2[indices[i * 3 + j] * 3 + 2] += tdir_z; } } for(int i = 0; i < max_index; i++) { float t_x = tan1[i * 3]; float t_y = tan1[i * 3 + 1]; float t_z = tan1[i * 3 + 2]; float n_x = normals[i * 3]; float n_y = normals[i * 3 + 1]; float n_z = normals[i * 3 + 2]; // Gram-Schmidt orthogonalize // tangent[a].xyz = (t - n * Dot(n, t)).Normalize(); float dot = n_x * t_x + n_y * t_y + n_z * t_z; float gso_x = t_x - n_x * dot; float gso_y = t_y - n_y * dot; float gso_z = t_z - n_z * dot; float n = gso_x * gso_x + gso_y * gso_y + gso_z * gso_z; if(n != 0) { n = 1 / n; tangents[i * 4] = gso_x * n; tangents[i * 4 + 1] = gso_y * n; tangents[i * 4 + 2] = gso_z * n; } else { // Not sure on the best thing to put here. Should hopefully // never be zero anyway. tangents[i * 4] = 0; tangents[i * 4 + 1] = 1; tangents[i * 4 + 2] = 0; } // Calculate handedness //tangent[a].angle = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; float c_x = n_y * t_z - n_z * t_y; float c_y = n_z * t_x - n_x * t_z; float c_z = n_x * t_y - n_y * t_x; dot = c_x * tan2[i * 3] + c_y * tan2[i * 3 + 1] + c_z * tan2[i * 3 + 2]; tangents[i * 4 + 3] = dot < 0 ? -1 : 1; } } /** * Generate tangent space vectors and Binormals (Bitangents). Assumes * that per-vertex normals are provided and it is a triangle array. * * @param numTriangles The number of triangles to process - * assuming a triangle array * @param coords The list of coordinates to process as a flat list * @param normals The list of normals, one per vertex, flattened * @param texCoords The list of 2D texture coordinates, one per * vertex, flattened * @param tangents The array to put the returned tangents in, must * be 4x the number of coordinates as it is provided in x,y,z,angle * form * @throws NullPointerException One of the arrays provided was * null. Message contains the details of which one */ public static void createTangents(int numTriangles, float[] coords, float[] normals, float[] texCoords, float[] tangents) { if(coords == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_COORDS_PROP); throw new NullPointerException(msg); } if(normals == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_NORMALS_PROP); throw new NullPointerException(msg); } if(texCoords == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_TEXCOORD_PROP); throw new NullPointerException(msg); } if(tangents == null) { I18nManager intl_mgr = I18nManager.getManager(); String msg = intl_mgr.getString(MISSING_TANGENT_PROP); throw new NullPointerException(msg); } int num_vertex = numTriangles * 3; float[] tan1 = new float[num_vertex * 3]; float[] tan2 = new float[num_vertex * 3]; int vtx = 0; for(int i = 0; i < numTriangles; i++) { vtx = i * 3; float x1 = coords[(vtx + 1) * 3] - coords[vtx * 3]; float x2 = coords[(vtx + 2) * 3] - coords[vtx * 3]; float y1 = coords[(vtx + 1) * 3 + 1] - coords[vtx * 3 + 1]; float y2 = coords[(vtx + 2) * 3 + 1] - coords[vtx * 3 + 1]; float z1 = coords[(vtx + 1) * 3 + 2] - coords[vtx * 3 + 2]; float z2 = coords[(vtx + 2) * 3 + 2] - coords[vtx * 3 + 2]; float s1 = texCoords[(vtx + 1) * 2] - texCoords[vtx * 2]; float s2 = texCoords[(vtx + 2) * 2] - texCoords[vtx * 2]; float t1 = texCoords[(vtx + 1) * 2 + 1] - texCoords[vtx * 2 + 1]; float t2 = texCoords[(vtx + 2) * 2 + 1] - texCoords[vtx * 2 + 1]; float r = 1.0f / (s1 * t2 - s2 * t1); float sdir_x = (t2 * x1 - t1 * x2) * r; float sdir_y = (t2 * y1 - t1 * y2) * r; float sdir_z = (t2 * z1 - t1 * z2) * r; float tdir_x = (s1 * x2 - s2 * x1) * r; float tdir_y = (s1 * y2 - s2 * y1) * r; float tdir_z = (s1 * z2 - s2 * z1) * r; int idx = 0; for (int j = 0; j < 3; j++) { idx = (vtx + j) * 3; tan1[idx] = sdir_x; tan1[idx + 1] = sdir_y; tan1[idx + 2] = sdir_z; tan2[idx] = tdir_x; tan2[idx + 1] = tdir_y; tan2[idx + 2] = tdir_z; } } int idx = 0; int t_idx = 0; for(int i = 0; i < num_vertex; i++) { idx = i * 3; t_idx = i * 4; float t_x = tan1[idx]; float t_y = tan1[idx + 1]; float t_z = tan1[idx + 2]; float n_x = normals[idx]; float n_y = normals[idx + 1]; float n_z = normals[idx + 2]; // Gram-Schmidt orthogonalize // tangent[a].xyz = (t - n * Dot(n, t)).Normalize(); float dot = n_x * t_x + n_y * t_y + n_z * t_z; float gso_x = t_x - n_x * dot; float gso_y = t_y - n_y * dot; float gso_z = t_z - n_z * dot; float n = gso_x * gso_x + gso_y * gso_y + gso_z * gso_z; if(n != 0) { n = 1 / n; tangents[t_idx] = gso_x * n; tangents[t_idx + 1] = gso_y * n; tangents[t_idx + 2] = gso_z * n; } else { // Not sure on the best thing to put here. Should hopefully // never be zero anyway. tangents[t_idx] = 0; tangents[t_idx + 1] = 1; tangents[t_idx + 2] = 0; } // Calculate handedness //tangent[a].angle = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; float c_x = n_y * t_z - n_z * t_y; float c_y = n_z * t_x - n_x * t_z; float c_z = n_x * t_y - n_y * t_x; dot = c_x * tan2[idx] + c_y * tan2[idx + 1] + c_z * tan2[idx + 2]; tangents[t_idx + 3] = dot < 0 ? -1 : 1; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy