org.j3d.util.TriangleUtils Maven / Gradle / Ivy
/*****************************************************************************
* 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