@ -38,6 +38,7 @@ import java.util.logging.Logger;
import com.jme3.bounding.BoundingBox ;
import com.jme3.bounding.BoundingSphere ;
import com.jme3.bounding.BoundingVolume ;
import com.jme3.math.Triangle ;
import com.jme3.math.Vector2f ;
import com.jme3.math.Vector3f ;
import com.jme3.scene.Geometry ;
@ -45,7 +46,6 @@ import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer ;
import com.jme3.scene.VertexBuffer.Format ;
import com.jme3.scene.VertexBuffer.Usage ;
import com.jme3.texture.Texture.Type ;
import com.jme3.util.BufferUtils ;
/ * *
@ -55,6 +55,7 @@ import com.jme3.util.BufferUtils;
public class UVCoordinatesGenerator {
private static final Logger LOGGER = Logger . getLogger ( UVCoordinatesGenerator . class . getName ( ) ) ;
// texture UV coordinates types
public static final int TEXCO_ORCO = 1 ;
public static final int TEXCO_REFL = 2 ;
public static final int TEXCO_NORM = 4 ;
@ -70,49 +71,61 @@ public class UVCoordinatesGenerator {
public static final int TEXCO_TANGENT = 4096 ;
// still stored in vertex->accum, 1 D
public static final int TEXCO_PARTICLE_OR_STRAND = 8192 ; // strand is used
// for normal
// materials,
// particle for halo
// materials
public static final int TEXCO_STRESS = 16384 ;
public static final int TEXCO_SPEED = 32768 ;
// 2D texture mapping (projection)
public static final int PROJECTION_FLAT = 0 ;
public static final int PROJECTION_CUBE = 1 ;
public static final int PROJECTION_TUBE = 2 ;
public static final int PROJECTION_SPHERE = 3 ;
/ * *
* This method generates UV coordinates for the given geometries .
* This method generates UV coordinates for the given mesh .
* IMPORTANT ! This method assumes that all geometries represent one node .
* Each containing mesh with separate material .
* So all meshes have the same reference to vertex table which stores all their vertices .
* @param texco
* texture coordinates type
* @param textureType
* the type of the texture ( only 2D and 3D )
* @param projection
* the projection type for 2D textures
* @param textureDimension
* the dimension of the texture ( only 2D and 3D )
* @param geometries
* a list of geometries that will have coordinates applied
* a list of geometries the UV coordinates will be applied to
* /
public static void generateUVCoordinates ( int texco , Type textureType , List < Geometry > geometries ) {
for ( Geometry geometry : geometries ) {
UVCoordinatesGenerator . generateUVCoordinates ( texco , textureType , geometry . getMesh ( ) ) ;
public static void generateUVCoordinates ( int texco , int projection , int textureDimension , List < Geometry > geometries ) {
if ( textureDimension ! = 2 & & textureDimension ! = 3 ) {
throw new IllegalStateException ( "Unsupported texture dimension: " + textureDimension ) ;
}
}
/ * *
* This method generates UV coordinates for the given mesh .
* @param texco
* texture coordinates type
* @param textureType
* the type of the texture ( only 2D and 3D )
* @param mesh
* a mesh that will have coordinates applied
* /
public static void generateUVCoordinates ( int texco , Type textureType , Mesh mesh ) {
VertexBuffer result = null ;
VertexBuffer result = new VertexBuffer ( VertexBuffer . Type . TexCoord ) ;
Mesh mesh = geometries . get ( 0 ) . getMesh ( ) ;
BoundingBox bb = UVCoordinatesGenerator . getBoundingBox ( geometries ) ;
switch ( texco ) {
case TEXCO_ORCO :
if ( textureType = = Type . TwoDimensional ) {
} else if ( textureType = = Type . ThreeDimensional ) {
BoundingBox bb = UVCoordinatesGenerator . getBoundingBox ( mesh ) ;
result = new VertexBuffer ( com . jme3 . scene . VertexBuffer . Type . TexCoord ) ;
FloatBuffer positions = mesh . getFloatBuffer ( com . jme3 . scene . VertexBuffer . Type . Position ) ;
float [ ] uvCoordinates = BufferUtils . getFloatArray ( positions ) ;
float [ ] uvCoordinates = null ;
if ( textureDimension = = 2 ) {
switch ( projection ) {
case PROJECTION_FLAT :
uvCoordinates = UVCoordinatesGenerator . flatProjection ( mesh , bb ) ;
break ;
case PROJECTION_CUBE :
uvCoordinates = UVCoordinatesGenerator . cubeProjection ( mesh , bb ) ;
break ;
case PROJECTION_TUBE :
uvCoordinates = UVCoordinatesGenerator . tubeProjection ( mesh , bb ) ;
break ;
case PROJECTION_SPHERE :
uvCoordinates = UVCoordinatesGenerator . sphereProjection ( mesh , bb ) ;
break ;
default :
throw new IllegalStateException ( "Unknown projection type: " + projection ) ;
}
} else {
FloatBuffer positions = mesh . getFloatBuffer ( VertexBuffer . Type . Position ) ;
uvCoordinates = BufferUtils . getFloatArray ( positions ) ;
Vector3f min = bb . getMin ( null ) ;
float [ ] ext = new float [ ] { bb . getXExtent ( ) * 2 , bb . getYExtent ( ) * 2 , bb . getZExtent ( ) * 2 } ;
@ -122,10 +135,22 @@ public class UVCoordinatesGenerator {
uvCoordinates [ i + 1 ] = ( uvCoordinates [ i + 1 ] - min . y ) / ext [ 1 ] ;
uvCoordinates [ i + 2 ] = ( uvCoordinates [ i + 2 ] - min . z ) / ext [ 2 ] ;
}
result . setupData ( Usage . Static , 3 , Format . Float , BufferUtils . createFloatBuffer ( uvCoordinates ) ) ;
result . setupData ( Usage . Static , textureDimension , Format . Float , BufferUtils . createFloatBuffer ( uvCoordinates ) ) ;
}
result . setupData ( Usage . Static , textureDimension , Format . Float , BufferUtils . createFloatBuffer ( uvCoordinates ) ) ;
break ;
case TEXCO_UV :
if ( textureDimension = = 2 ) {
FloatBuffer uvCoordinatesBuffer = BufferUtils . createFloatBuffer ( mesh . getVertexCount ( ) < < 1 ) ;
Vector2f [ ] data = new Vector2f [ ] { new Vector2f ( 0 , 1 ) , new Vector2f ( 0 , 0 ) , new Vector2f ( 1 , 0 ) } ;
for ( int i = 0 ; i < mesh . getVertexCount ( ) ; + + i ) {
Vector2f uv = data [ i % 3 ] ;
uvCoordinatesBuffer . put ( uv . x ) ;
uvCoordinatesBuffer . put ( uv . y ) ;
}
result . setupData ( Usage . Static , textureDimension , Format . Float , uvCoordinatesBuffer ) ;
} else {
throw new IllegalStateException ( "Unsupported texture type: " + textureType ) ;
}
break ;
case TEXCO_GLOB :
@ -133,8 +158,6 @@ public class UVCoordinatesGenerator {
break ;
case TEXCO_TANGENT :
break ;
case TEXCO_UV :
break ;
case TEXCO_STRESS :
@ -157,38 +180,110 @@ public class UVCoordinatesGenerator {
throw new IllegalStateException ( "Unknown texture coordinates value: " + texco ) ;
}
mesh . clearBuffer ( VertexBuffer . Type . TexCoord ) ; // in case there are coordinates already set
mesh . setBuffer ( result ) ;
// each mesh will have the same coordinates
for ( Geometry geometry : geometries ) {
mesh = geometry . getMesh ( ) ;
mesh . clearBuffer ( VertexBuffer . Type . TexCoord ) ; // in case there are coordinates already set
mesh . setBuffer ( result ) ;
}
}
/ * *
* Flat projection for 2D textures .
* @param mesh
* mesh that is to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
* /
public Vector2f [ ] flatProjection ( Mesh mesh ) {
return null ; // TODO: implement
private static float [ ] flatProjection ( Mesh mesh , BoundingBox bb ) {
if ( bb = = null ) {
bb = UVCoordinatesGenerator . getBoundingBox ( mesh ) ;
}
Vector3f min = bb . getMin ( null ) ;
float [ ] ext = new float [ ] { bb . getXExtent ( ) * 2 . 0f , bb . getYExtent ( ) * 2 . 0f } ;
FloatBuffer positions = mesh . getFloatBuffer ( com . jme3 . scene . VertexBuffer . Type . Position ) ;
float [ ] uvCoordinates = new float [ positions . limit ( ) / 3 * 2 ] ;
for ( int i = 0 , j = 0 ; i < positions . limit ( ) ; i + = 3 , j + = 2 ) {
uvCoordinates [ j ] = ( positions . get ( i ) - min . x ) / ext [ 0 ] ;
uvCoordinates [ j + 1 ] = ( positions . get ( i + 1 ) - min . y ) / ext [ 1 ] ;
// skip the Z-coordinate
}
return uvCoordinates ;
}
/ * *
* Cube projection for 2D textures .
* @param mesh
* mesh that is to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
* /
public Vector2f [ ] cubeProjection ( Mesh mesh ) {
return null ; // TODO: implement
private static float [ ] cubeProjection ( Mesh mesh , BoundingBox bb ) {
Triangle triangle = new Triangle ( ) ;
Vector3f x = new Vector3f ( 1 , 0 , 0 ) ;
Vector3f y = new Vector3f ( 0 , 1 , 0 ) ;
Vector3f z = new Vector3f ( 0 , 0 , 1 ) ;
Vector3f min = bb . getMin ( null ) ;
float [ ] ext = new float [ ] { bb . getXExtent ( ) * 2 . 0f , bb . getYExtent ( ) * 2 . 0f , bb . getZExtent ( ) * 2 . 0f } ;
float [ ] uvCoordinates = new float [ mesh . getTriangleCount ( ) * 6 ] ; // 6 == 3 * 2
float borderAngle = ( float ) Math . sqrt ( 2 . 0f ) / 2 . 0f ;
for ( int i = 0 , pointIndex = 0 ; i < mesh . getTriangleCount ( ) ; + + i ) {
mesh . getTriangle ( i , triangle ) ;
Vector3f n = triangle . getNormal ( ) ;
float dotNX = Math . abs ( n . dot ( x ) ) ;
float dorNY = Math . abs ( n . dot ( y ) ) ;
float dotNZ = Math . abs ( n . dot ( z ) ) ;
if ( dotNX > borderAngle ) {
if ( dotNZ < borderAngle ) { // discard X-coordinate
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . z - min . z ) / ext [ 2 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . z - min . z ) / ext [ 2 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . z - min . z ) / ext [ 2 ] ;
} else { // discard Z-coordinate
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . y - min . y ) / ext [ 1 ] ;
}
} else {
if ( dorNY > borderAngle ) { // discard Y-coordinate
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . z - min . z ) / ext [ 2 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . z - min . z ) / ext [ 2 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . z - min . z ) / ext [ 2 ] ;
} else { // discard Z-coordinate
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get1 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get2 ( ) . y - min . y ) / ext [ 1 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . x - min . x ) / ext [ 0 ] ;
uvCoordinates [ pointIndex + + ] = ( triangle . get3 ( ) . y - min . y ) / ext [ 1 ] ;
}
}
triangle . setNormal ( null ) ; //clear the previous normal vector
}
return uvCoordinates ;
}
/ * *
* Tube projection for 2D textures .
* @param mesh
* mesh that is to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
* /
public Vector2f [ ] tubeProjection ( Mesh mesh ) {
private static float [ ] tubeProjection ( Mesh mesh , BoundingBox bb ) {
return null ; // TODO: implement
}
@ -196,9 +291,11 @@ public class UVCoordinatesGenerator {
* Sphere projection for 2D textures .
* @param mesh
* mesh that is to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
* /
public Vector2f [ ] sphereProjection ( Mesh mesh ) {
private static float [ ] sphereProjection ( Mesh mesh , BoundingBox bb ) {
return null ; // TODO: implement
// Vector2f[] uvTable = new Vector2f[vertexList.size()];
// Ray ray = new Ray();