@ -29,9 +29,11 @@
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
* /
package com.jme3.util ;
package com.jme3.util ;
import com.jme3.scene.VertexBuffer ;
import com.jme3.scene.VertexBuffer.Format ;
import com.jme3.scene.VertexBuffer.Usage ;
import java.util.logging.Level ;
import java.util.logging.Level ;
import com.jme3.scene.mesh.IndexBuffer ;
import com.jme3.scene.mesh.IndexBuffer ;
import com.jme3.scene.Geometry ;
import com.jme3.scene.Geometry ;
@ -59,7 +61,6 @@ public class TangentBinormalGenerator {
private static final float ZERO_TOLERANCE = 0 . 0000001f ;
private static final float ZERO_TOLERANCE = 0 . 0000001f ;
private static final Logger log = Logger . getLogger (
private static final Logger log = Logger . getLogger (
TangentBinormalGenerator . class . getName ( ) ) ;
TangentBinormalGenerator . class . getName ( ) ) ;
private static float toleranceAngle ;
private static float toleranceAngle ;
private static float toleranceDot ;
private static float toleranceDot ;
@ -68,17 +69,18 @@ public class TangentBinormalGenerator {
}
}
private static class VertexData {
private static class VertexData {
public final Vector3f tangent = new Vector3f ( ) ;
public final Vector3f tangent = new Vector3f ( ) ;
public final Vector3f binormal = new Vector3f ( ) ;
public final Vector3f binormal = new Vector3f ( ) ;
public final List < TriangleData > triangles =
public final List < TriangleData > triangles =
new ArrayList < TriangleData > ( ) ;
new ArrayList < TriangleData > ( ) ;
public VertexData ( ) {
public VertexData ( ) {
}
}
}
}
public static class TriangleData {
public static class TriangleData {
public final Vector3f tangent ;
public final Vector3f tangent ;
public final Vector3f binormal ;
public final Vector3f binormal ;
public final Vector3f normal ;
public final Vector3f normal ;
@ -88,8 +90,7 @@ public class TangentBinormalGenerator {
public TriangleData ( Vector3f tangent , Vector3f binormal ,
public TriangleData ( Vector3f tangent , Vector3f binormal ,
Vector3f normal ,
Vector3f normal ,
int index0 , int index1 , int index2 )
int index0 , int index1 , int index2 ) {
{
this . tangent = tangent ;
this . tangent = tangent ;
this . binormal = binormal ;
this . binormal = binormal ;
this . normal = normal ;
this . normal = normal ;
@ -140,26 +141,49 @@ public class TangentBinormalGenerator {
VertexData [ ] vertices ;
VertexData [ ] vertices ;
switch ( mesh . getMode ( ) ) {
switch ( mesh . getMode ( ) ) {
case Triangles :
case Triangles :
vertices = processTriangles ( mesh , index , v , t ) ; break ;
vertices = processTriangles ( mesh , index , v , t ) ;
break ;
case TriangleStrip :
case TriangleStrip :
vertices = processTriangleStrip ( mesh , index , v , t ) ; break ;
vertices = processTriangleStrip ( mesh , index , v , t ) ;
break ;
case TriangleFan :
case TriangleFan :
vertices = processTriangleFan ( mesh , index , v , t ) ; break ;
vertices = processTriangleFan ( mesh , index , v , t ) ;
default : throw new UnsupportedOperationException (
break ;
default :
throw new UnsupportedOperationException (
mesh . getMode ( ) + " is not supported." ) ;
mesh . getMode ( ) + " is not supported." ) ;
}
}
processTriangleData ( mesh , vertices , approxTangents ) ;
processTriangleData ( mesh , vertices , approxTangents ) ;
//if the mesh has a bind pose, we need to generate the bind pose for the tangent buffer
if ( mesh . getBuffer ( Type . BindPosePosition ) ! = null ) {
VertexBuffer tangents = mesh . getBuffer ( Type . Tangent ) ;
if ( tangents ! = null ) {
VertexBuffer bindTangents = new VertexBuffer ( Type . BindPoseTangent ) ;
bindTangents . setupData ( Usage . CpuOnly ,
4 ,
Format . Float ,
BufferUtils . clone ( tangents . getData ( ) ) ) ;
if ( mesh . getBuffer ( Type . BindPoseTangent ) ! = null ) {
mesh . clearBuffer ( Type . BindPoseTangent ) ;
}
mesh . setBuffer ( bindTangents ) ;
tangents . setUsage ( Usage . Stream ) ;
}
}
}
}
private static VertexData [ ] processTriangles ( Mesh mesh ,
private static VertexData [ ] processTriangles ( Mesh mesh ,
int [ ] index , Vector3f [ ] v , Vector2f [ ] t )
int [ ] index , Vector3f [ ] v , Vector2f [ ] t ) {
{
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
if ( mesh . getBuffer ( Type . TexCoord ) = = null )
if ( mesh . getBuffer ( Type . TexCoord ) = = null ) {
throw new IllegalArgumentException ( "Can only generate tangents for "
throw new IllegalArgumentException ( "Can only generate tangents for "
+ "meshes with texture coordinates" ) ;
+ "meshes with texture coordinates" ) ;
}
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
@ -182,9 +206,9 @@ public class TangentBinormalGenerator {
return vertices ;
return vertices ;
}
}
private static VertexData [ ] processTriangleStrip ( Mesh mesh ,
private static VertexData [ ] processTriangleStrip ( Mesh mesh ,
int [ ] index , Vector3f [ ] v , Vector2f [ ] t )
int [ ] index , Vector3f [ ] v , Vector2f [ ] t ) {
{
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
@ -230,9 +254,9 @@ public class TangentBinormalGenerator {
return vertices ;
return vertices ;
}
}
private static VertexData [ ] processTriangleFan ( Mesh mesh ,
private static VertexData [ ] processTriangleFan ( Mesh mesh ,
int [ ] index , Vector3f [ ] v , Vector2f [ ] t )
int [ ] index , Vector3f [ ] v , Vector2f [ ] t ) {
{
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
IndexBuffer indexBuffer = mesh . getIndexBuffer ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
FloatBuffer textureBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . TexCoord ) . getData ( ) ;
@ -279,10 +303,8 @@ public class TangentBinormalGenerator {
return ( a . subtract ( b ) . cross ( c . subtract ( b ) ) ) . lengthSquared ( ) = = 0 ;
return ( a . subtract ( b ) . cross ( c . subtract ( b ) ) ) . lengthSquared ( ) = = 0 ;
}
}
public static TriangleData processTriangle ( int [ ] index ,
public static TriangleData processTriangle ( int [ ] index ,
Vector3f [ ] v , Vector2f [ ] t )
Vector3f [ ] v , Vector2f [ ] t ) {
{
Vector3f edge1 = new Vector3f ( ) ;
Vector3f edge1 = new Vector3f ( ) ;
Vector3f edge2 = new Vector3f ( ) ;
Vector3f edge2 = new Vector3f ( ) ;
Vector2f edge1uv = new Vector2f ( ) ;
Vector2f edge1uv = new Vector2f ( ) ;
@ -298,9 +320,9 @@ public class TangentBinormalGenerator {
boolean normalize = false ;
boolean normalize = false ;
if ( Math . abs ( det ) < ZERO_TOLERANCE ) {
if ( Math . abs ( det ) < ZERO_TOLERANCE ) {
log . log ( Level . WARNING , "Colinear uv coordinates for triangle " +
log . log ( Level . WARNING , "Colinear uv coordinates for triangle "
"[{0}, {1}, {2}]; tex0 = [{3}, {4}], " +
+ "[{0}, {1}, {2}]; tex0 = [{3}, {4}], "
"tex1 = [{5}, {6}], tex2 = [{7}, {8}]" ,
+ "tex1 = [{5}, {6}], tex2 = [{7}, {8}]" ,
new Object [ ] { index [ 0 ] , index [ 1 ] , index [ 2 ] ,
new Object [ ] { index [ 0 ] , index [ 1 ] , index [ 2 ] ,
t [ 0 ] . x , t [ 0 ] . y , t [ 1 ] . x , t [ 1 ] . y , t [ 2 ] . x , t [ 2 ] . y } ) ;
t [ 0 ] . x , t [ 0 ] . y , t [ 1 ] . x , t [ 1 ] . y , t [ 2 ] . x , t [ 2 ] . y } ) ;
det = 1 ;
det = 1 ;
@ -316,10 +338,9 @@ public class TangentBinormalGenerator {
binormal . normalizeLocal ( ) ;
binormal . normalizeLocal ( ) ;
if ( Math . abs ( Math . abs ( tangent . dot ( binormal ) ) - 1 )
if ( Math . abs ( Math . abs ( tangent . dot ( binormal ) ) - 1 )
< ZERO_TOLERANCE )
< ZERO_TOLERANCE ) {
{
log . log ( Level . WARNING , "Vertices are on the same line "
log . log ( Level . WARNING , "Vertices are on the same line " +
+ "for triangle [{0}, {1}, {2}]." ,
"for triangle [{0}, {1}, {2}]." ,
new Object [ ] { index [ 0 ] , index [ 1 ] , index [ 2 ] } ) ;
new Object [ ] { index [ 0 ] , index [ 1 ] , index [ 2 ] } ) ;
}
}
@ -327,12 +348,16 @@ public class TangentBinormalGenerator {
tangent . x = ( edge2uv . y * edge1 . x - edge1uv . y * edge2 . x ) * factor ;
tangent . x = ( edge2uv . y * edge1 . x - edge1uv . y * edge2 . x ) * factor ;
tangent . y = ( edge2uv . y * edge1 . y - edge1uv . y * edge2 . y ) * factor ;
tangent . y = ( edge2uv . y * edge1 . y - edge1uv . y * edge2 . y ) * factor ;
tangent . z = ( edge2uv . y * edge1 . z - edge1uv . y * edge2 . z ) * factor ;
tangent . z = ( edge2uv . y * edge1 . z - edge1uv . y * edge2 . z ) * factor ;
if ( normalize ) tangent . normalizeLocal ( ) ;
if ( normalize ) {
tangent . normalizeLocal ( ) ;
}
binormal . x = ( edge1uv . x * edge2 . x - edge2uv . x * edge1 . x ) * factor ;
binormal . x = ( edge1uv . x * edge2 . x - edge2uv . x * edge1 . x ) * factor ;
binormal . y = ( edge1uv . x * edge2 . y - edge2uv . x * edge1 . y ) * factor ;
binormal . y = ( edge1uv . x * edge2 . y - edge2uv . x * edge1 . y ) * factor ;
binormal . z = ( edge1uv . x * edge2 . z - edge2uv . x * edge1 . z ) * factor ;
binormal . z = ( edge1uv . x * edge2 . z - edge2uv . x * edge1 . z ) * factor ;
if ( normalize ) binormal . normalizeLocal ( ) ;
if ( normalize ) {
binormal . normalizeLocal ( ) ;
}
tangent . cross ( binormal , normal ) ;
tangent . cross ( binormal , normal ) ;
normal . normalizeLocal ( ) ;
normal . normalizeLocal ( ) ;
@ -341,8 +366,7 @@ public class TangentBinormalGenerator {
tangent ,
tangent ,
binormal ,
binormal ,
normal ,
normal ,
index [ 0 ] , index [ 1 ] , index [ 2 ]
index [ 0 ] , index [ 1 ] , index [ 2 ] ) ;
) ;
}
}
public static void setToleranceAngle ( float angle ) {
public static void setToleranceAngle ( float angle ) {
@ -355,8 +379,7 @@ public class TangentBinormalGenerator {
}
}
private static void processTriangleData ( Mesh mesh , VertexData [ ] vertices ,
private static void processTriangleData ( Mesh mesh , VertexData [ ] vertices ,
boolean approxTangent )
boolean approxTangent ) {
{
FloatBuffer normalBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Normal ) . getData ( ) ;
FloatBuffer normalBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Normal ) . getData ( ) ;
FloatBuffer tangents = BufferUtils . createFloatBuffer ( vertices . length * 4 ) ;
FloatBuffer tangents = BufferUtils . createFloatBuffer ( vertices . length * 4 ) ;
@ -392,8 +415,8 @@ public class TangentBinormalGenerator {
tangentUnit . normalizeLocal ( ) ;
tangentUnit . normalizeLocal ( ) ;
if ( tangent . dot ( tangentUnit ) < toleranceDot ) {
if ( tangent . dot ( tangentUnit ) < toleranceDot ) {
log . log ( Level . WARNING ,
log . log ( Level . WARNING ,
"Angle between tangents exceeds tolerance " +
"Angle between tangents exceeds tolerance "
"for vertex {0}." , i ) ;
+ "for vertex {0}." , i ) ;
break ;
break ;
}
}
@ -402,8 +425,8 @@ public class TangentBinormalGenerator {
binormalUnit . normalizeLocal ( ) ;
binormalUnit . normalizeLocal ( ) ;
if ( binormal . dot ( binormalUnit ) < toleranceDot ) {
if ( binormal . dot ( binormalUnit ) < toleranceDot ) {
log . log ( Level . WARNING ,
log . log ( Level . WARNING ,
"Angle between binormals exceeds tolerance " +
"Angle between binormals exceeds tolerance "
"for vertex {0}." , i ) ;
+ "for vertex {0}." , i ) ;
break ;
break ;
}
}
}
}
@ -439,21 +462,18 @@ public class TangentBinormalGenerator {
if ( binormal . length ( ) > = ZERO_TOLERANCE ) {
if ( binormal . length ( ) > = ZERO_TOLERANCE ) {
binormal . cross ( givenNormal , tangent ) ;
binormal . cross ( givenNormal , tangent ) ;
tangent . normalizeLocal ( ) ;
tangent . normalizeLocal ( ) ;
}
} // if all fails use the tangent from the first triangle
// if all fails use the tangent from the first triangle
else {
else {
tangent . set ( triangles . get ( 0 ) . tangent ) ;
tangent . set ( triangles . get ( 0 ) . tangent ) ;
}
}
}
} else {
else {
tangent . divideLocal ( triangles . size ( ) ) ;
tangent . divideLocal ( triangles . size ( ) ) ;
}
}
tangentUnit . set ( tangent ) ;
tangentUnit . set ( tangent ) ;
tangentUnit . normalizeLocal ( ) ;
tangentUnit . normalizeLocal ( ) ;
if ( Math . abs ( Math . abs ( tangentUnit . dot ( givenNormal ) ) - 1 )
if ( Math . abs ( Math . abs ( tangentUnit . dot ( givenNormal ) ) - 1 )
< ZERO_TOLERANCE )
< ZERO_TOLERANCE ) {
{
log . log ( Level . WARNING ,
log . log ( Level . WARNING ,
"Normal and tangent are parallel for vertex {0}." , i ) ;
"Normal and tangent are parallel for vertex {0}." , i ) ;
}
}
@ -467,28 +487,24 @@ public class TangentBinormalGenerator {
if ( tangent . length ( ) > = ZERO_TOLERANCE ) {
if ( tangent . length ( ) > = ZERO_TOLERANCE ) {
givenNormal . cross ( tangent , binormal ) ;
givenNormal . cross ( tangent , binormal ) ;
binormal . normalizeLocal ( ) ;
binormal . normalizeLocal ( ) ;
}
} // if all fails use the binormal from the first triangle
// if all fails use the binormal from the first triangle
else {
else {
binormal . set ( triangles . get ( 0 ) . binormal ) ;
binormal . set ( triangles . get ( 0 ) . binormal ) ;
}
}
}
} else {
else {
binormal . divideLocal ( triangles . size ( ) ) ;
binormal . divideLocal ( triangles . size ( ) ) ;
}
}
binormalUnit . set ( binormal ) ;
binormalUnit . set ( binormal ) ;
binormalUnit . normalizeLocal ( ) ;
binormalUnit . normalizeLocal ( ) ;
if ( Math . abs ( Math . abs ( binormalUnit . dot ( givenNormal ) ) - 1 )
if ( Math . abs ( Math . abs ( binormalUnit . dot ( givenNormal ) ) - 1 )
< ZERO_TOLERANCE )
< ZERO_TOLERANCE ) {
{
log . log ( Level . WARNING ,
log . log ( Level . WARNING ,
"Normal and binormal are parallel for vertex {0}." , i ) ;
"Normal and binormal are parallel for vertex {0}." , i ) ;
}
}
if ( Math . abs ( Math . abs ( binormalUnit . dot ( tangentUnit ) ) - 1 )
if ( Math . abs ( Math . abs ( binormalUnit . dot ( tangentUnit ) ) - 1 )
< ZERO_TOLERANCE )
< ZERO_TOLERANCE ) {
{
log . log ( Level . WARNING ,
log . log ( Level . WARNING ,
"Tangent and binormal are parallel for vertex {0}." , i ) ;
"Tangent and binormal are parallel for vertex {0}." , i ) ;
}
}
@ -503,8 +519,7 @@ public class TangentBinormalGenerator {
tangents . put ( ( i * 4 ) + 1 , tangent . y ) ;
tangents . put ( ( i * 4 ) + 1 , tangent . y ) ;
tangents . put ( ( i * 4 ) + 2 , tangent . z ) ;
tangents . put ( ( i * 4 ) + 2 , tangent . z ) ;
tangents . put ( ( i * 4 ) + 3 , wCoord ) ;
tangents . put ( ( i * 4 ) + 3 , wCoord ) ;
}
} else {
else {
tangents . put ( ( i * 4 ) , tangent . x ) ;
tangents . put ( ( i * 4 ) , tangent . x ) ;
tangents . put ( ( i * 4 ) + 1 , tangent . y ) ;
tangents . put ( ( i * 4 ) + 1 , tangent . y ) ;
tangents . put ( ( i * 4 ) + 2 , tangent . z ) ;
tangents . put ( ( i * 4 ) + 2 , tangent . z ) ;
@ -519,11 +534,12 @@ public class TangentBinormalGenerator {
}
}
public static Mesh genTbnLines ( Mesh mesh , float scale ) {
public static Mesh genTbnLines ( Mesh mesh , float scale ) {
if ( mesh . getBuffer ( Type . Tangent ) = = null )
if ( mesh . getBuffer ( Type . Tangent ) = = null ) {
return genNormalLines ( mesh , scale ) ;
return genNormalLines ( mesh , scale ) ;
else
} else {
return genTangentLines ( mesh , scale ) ;
return genTangentLines ( mesh , scale ) ;
}
}
}
public static Mesh genNormalLines ( Mesh mesh , float scale ) {
public static Mesh genNormalLines ( Mesh mesh , float scale ) {
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;
FloatBuffer vertexBuffer = ( FloatBuffer ) mesh . getBuffer ( Type . Position ) . getData ( ) ;